lisse 0.1.0 copy "lisse: ^0.1.0" to clipboard
lisse: ^0.1.0 copied to clipboard

Smooth-corner (squircle) rendering for Flutter. Figma squircle, arc, superellipse and clothoid corners as a ShapeBorder — clip, border and shadow trace the curve natively. Pure Dart, every target.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:lisse/lisse.dart';

void main() => runApp(const LisseGalleryApp());

const Color _bg = Color(0xFFF1F1F4);
const Color _ink = Color(0xFF18181B);
const Color _muted = Color(0xFF71717A);
const Color _accent = Color(0xFF4F46E5);
const Color _accent2 = Color(0xFF06B6D4);

class LisseGalleryApp extends StatelessWidget {
  const LisseGalleryApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Lisse for Flutter',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(scaffoldBackgroundColor: _bg, fontFamily: 'Roboto'),
      home: const _Gallery(),
    );
  }
}

class _Gallery extends StatelessWidget {
  const _Gallery();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ConstrainedBox(
          constraints: const BoxConstraints(maxWidth: 1040),
          child: ListView(
            padding: const EdgeInsets.fromLTRB(32, 56, 32, 80),
            children: [
              const Text(
                'Lisse',
                style: TextStyle(
                  fontSize: 44,
                  fontWeight: FontWeight.w700,
                  color: _ink,
                  letterSpacing: -1,
                ),
              ),
              const SizedBox(height: 6),
              const Text(
                'Smooth corners for Flutter — squircle, arc, '
                'superellipse and clothoid, as a native ShapeBorder.',
                style: TextStyle(fontSize: 16, color: _muted),
              ),
              const SizedBox(height: 44),

              _section('Curve families', 'Same 56px radius, four curves.'),
              Wrap(
                spacing: 20,
                runSpacing: 20,
                children: [
                  _curveTile('arc', LisseCurve.arc),
                  _curveTile('squircle', LisseCurve.squircle),
                  _curveTile('superellipse', LisseCurve.superellipse),
                  _curveTile('clothoid', LisseCurve.clothoid),
                ],
              ),
              const SizedBox(height: 44),

              _section('Squircle smoothing', '0 (arc) → 1 (max).'),
              Wrap(
                spacing: 20,
                runSpacing: 20,
                children: [
                  for (final s in const [0.0, 0.3, 0.6, 1.0])
                    _labelled(
                      's = $s',
                      _fill(LisseCorners.all(radius: 52, smoothing: s)),
                    ),
                ],
              ),
              const SizedBox(height: 44),

              _section(
                'Superellipse exponent',
                'n = 2 is a circle; higher is squarer.',
              ),
              Wrap(
                spacing: 20,
                runSpacing: 20,
                children: [
                  for (final n in const [2.0, 4.0, 6.0, 8.0])
                    _labelled(
                      'n = $n',
                      _fill(
                        LisseCorners.all(
                          radius: 52,
                          curve: LisseCurve.superellipse,
                          exponent: n,
                        ),
                      ),
                    ),
                ],
              ),
              const SizedBox(height: 44),

              _section(
                'Effects',
                'Shadows, borders and fills tracing the curve.',
              ),
              Wrap(
                spacing: 20,
                runSpacing: 20,
                children: [
                  _labelled(
                    'drop shadow',
                    SmoothBox(
                      width: 150,
                      height: 110,
                      corners: LisseCorners.all(radius: 34),
                      color: Colors.white,
                      shadows: const [
                        BoxShadow(
                          color: Color(0x33000000),
                          blurRadius: 26,
                          offset: Offset(0, 12),
                        ),
                      ],
                    ),
                  ),
                  _labelled(
                    'inner shadow',
                    SmoothBox(
                      width: 150,
                      height: 110,
                      corners: LisseCorners.all(radius: 34),
                      color: const Color(0xFFE6E6EB),
                      innerShadows: const [
                        LisseInnerShadow(
                          color: Color(0x73000000),
                          blur: 18,
                          spread: 1,
                          offset: Offset(0, 7),
                        ),
                      ],
                    ),
                  ),
                  _labelled(
                    'solid border',
                    SmoothBox(
                      width: 150,
                      height: 110,
                      corners: LisseCorners.all(radius: 34),
                      color: Colors.white,
                      side: const BorderSide(color: _accent, width: 3),
                    ),
                  ),
                  _labelled(
                    'concentric',
                    SmoothBox(
                      width: 150,
                      height: 110,
                      corners: LisseCorners.all(radius: 34),
                      color: Colors.white,
                      borders: const [
                        LisseBorderLayer(width: 4, color: _accent),
                        LisseBorderLayer(width: 3, color: _accent2),
                      ],
                    ),
                  ),
                  _labelled(
                    'gradient fill',
                    SmoothBox(
                      width: 150,
                      height: 110,
                      corners: LisseCorners.all(radius: 34),
                      gradient: const LinearGradient(
                        colors: [_accent, _accent2],
                        begin: Alignment.topLeft,
                        end: Alignment.bottomRight,
                      ),
                    ),
                  ),
                  _labelled(
                    'gradient border',
                    SmoothBox(
                      width: 150,
                      height: 110,
                      corners: LisseCorners.all(radius: 34),
                      color: Colors.white,
                      borders: const [
                        LisseBorderLayer(
                          width: 5,
                          gradient: LinearGradient(colors: [_accent, _accent2]),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 28),

              _section(
                'Border styles',
                'dashed · dotted · double · groove · ridge',
              ),
              Wrap(
                spacing: 20,
                runSpacing: 20,
                children: [
                  for (final e in const [
                    ['dashed', LisseBorderStyle.dashed],
                    ['dotted', LisseBorderStyle.dotted],
                    ['double', LisseBorderStyle.doubleLine],
                    ['groove', LisseBorderStyle.groove],
                    ['ridge', LisseBorderStyle.ridge],
                  ])
                    _labelled(
                      e[0] as String,
                      SmoothBox(
                        width: 132,
                        height: 100,
                        corners: LisseCorners.all(radius: 30),
                        color: Colors.white,
                        borders: [
                          LisseBorderLayer(
                            width: 6,
                            color: _accent,
                            style: e[1] as LisseBorderStyle,
                          ),
                        ],
                      ),
                    ),
                ],
              ),
              const SizedBox(height: 44),

              _section(
                'Per-corner',
                'Each corner its own radius, curve and smoothing.',
              ),
              Wrap(
                spacing: 20,
                runSpacing: 20,
                children: [
                  _labelled(
                    'asymmetric',
                    _fillSized(
                      220,
                      130,
                      LisseCorners.only(
                        topLeft: const LisseCorner(radius: 12),
                        topRight: const LisseCorner(radius: 44, smoothing: 0.6),
                        bottomRight: const LisseCorner(radius: 0),
                        bottomLeft: const LisseCorner(
                          radius: 60,
                          smoothing: 0.3,
                        ),
                      ),
                    ),
                  ),
                  _labelled(
                    'pill',
                    _fillSized(220, 96, LisseCorners.all(radius: 80)),
                  ),
                ],
              ),
              const SizedBox(height: 44),

              _section(
                'SmoothClip',
                'Clipping arbitrary content to the silhouette.',
              ),
              Align(
                alignment: Alignment.centerLeft,
                child: SmoothClip(
                  corners: LisseCorners.all(radius: 40),
                  child: Container(
                    width: 320,
                    height: 170,
                    decoration: const BoxDecoration(
                      gradient: LinearGradient(
                        colors: [_accent, _accent2],
                        begin: Alignment.topLeft,
                        end: Alignment.bottomRight,
                      ),
                    ),
                    alignment: Alignment.center,
                    child: const Text(
                      'clipped',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 26,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                  ),
                ),
              ),
              const SizedBox(height: 44),

              _section(
                'A card',
                'SmoothBox the way you would actually ship it.',
              ),
              Align(
                alignment: Alignment.centerLeft,
                child: SmoothBox(
                  width: 340,
                  corners: LisseCorners.all(radius: 28),
                  color: Colors.white,
                  padding: const EdgeInsets.all(22),
                  shadows: const [
                    BoxShadow(
                      color: Color(0x1A000000),
                      blurRadius: 30,
                      offset: Offset(0, 16),
                    ),
                  ],
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      SmoothBox(
                        width: 52,
                        height: 52,
                        corners: LisseCorners.all(radius: 16),
                        gradient: const LinearGradient(
                          colors: [_accent, _accent2],
                          begin: Alignment.topLeft,
                          end: Alignment.bottomRight,
                        ),
                        child: const Icon(Icons.bolt, color: Colors.white),
                      ),
                      const SizedBox(height: 16),
                      const Text(
                        'Continuous corners',
                        style: TextStyle(
                          fontSize: 19,
                          fontWeight: FontWeight.w700,
                          color: _ink,
                        ),
                      ),
                      const SizedBox(height: 6),
                      const Text(
                        'The same Figma squircle maths the web packages ship, '
                        'now as a Flutter ShapeBorder.',
                        style: TextStyle(
                          fontSize: 14,
                          color: _muted,
                          height: 1.45,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  static Widget _section(String title, String sub) => Padding(
    padding: const EdgeInsets.only(bottom: 18),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          title,
          style: const TextStyle(
            fontSize: 22,
            fontWeight: FontWeight.w700,
            color: _ink,
          ),
        ),
        const SizedBox(height: 2),
        Text(sub, style: const TextStyle(fontSize: 14, color: _muted)),
      ],
    ),
  );

  static Widget _labelled(String label, Widget child) => Column(
    mainAxisSize: MainAxisSize.min,
    children: [
      child,
      const SizedBox(height: 8),
      Text(
        label,
        style: const TextStyle(
          fontSize: 12.5,
          color: _muted,
          fontWeight: FontWeight.w500,
        ),
      ),
    ],
  );

  static Widget _curveTile(String name, LisseCurve curve) => _labelled(
    name,
    SmoothBox(
      width: 150,
      height: 150,
      corners: LisseCorners.all(radius: 56, curve: curve),
      gradient: const LinearGradient(
        colors: [_accent, _accent2],
        begin: Alignment.topLeft,
        end: Alignment.bottomRight,
      ),
    ),
  );

  static Widget _fill(LisseCorners corners) => _fillSized(150, 150, corners);

  static Widget _fillSized(double w, double h, LisseCorners corners) =>
      SmoothBox(width: w, height: h, corners: corners, color: _accent);
}
0
likes
150
points
80
downloads

Documentation

API reference

Publisher

verified publishercorne.rs

Weekly Downloads

Smooth-corner (squircle) rendering for Flutter. Figma squircle, arc, superellipse and clothoid corners as a ShapeBorder — clip, border and shadow trace the curve natively. Pure Dart, every target.

License

MIT (license)

Dependencies

flutter

More

Packages that depend on lisse