https://github.com/nemanjavlahovic/floekit
Elegant, modular UI building blocks for SwiftUI β design system, components, and utilities with built-in theming and accessibility
https://github.com/nemanjavlahovic/floekit
design-system ios macos modular-components swift swiftui swiftui-example
Last synced: 3 months ago
JSON representation
Elegant, modular UI building blocks for SwiftUI β design system, components, and utilities with built-in theming and accessibility
- Host: GitHub
- URL: https://github.com/nemanjavlahovic/floekit
- Owner: nemanjavlahovic
- Created: 2025-05-21T14:21:29.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-05-31T22:05:48.000Z (12 months ago)
- Last Synced: 2025-06-07T18:54:49.512Z (12 months ago)
- Topics: design-system, ios, macos, modular-components, swift, swiftui, swiftui-example
- Language: Swift
- Homepage:
- Size: 9.81 MB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# FloeKit

> **Elegant, modular UI building blocks for SwiftUI**
Inspired by floating ice sheets, **FloeKit** provides calm, elegant, and modular UI components designed for composability, design clarity, and reuse. It positions itself as a thoughtful layer *on top of SwiftUI*, offering a consistent design system with built-in theming, spacing, and typography.



π Table of Contents
- [β¨ Features](#-features)
- [π Installation](#-installation)
- [π§± Components](#-components)
- [FloeButton](#floebutton)
- [FloeTextField](#floetextfield)
- [FloeCard](#floecard)
- [FloeAvatar](#floeavatar)
- [FloeToast](#floetoast-new)
- [FloeTabBar](#floetabbar-new)
- [FloeSlider](#floeslider-new)
- [FloeTextView](#floetextview-new)
- [FloeProgressIndicator](#floeprogressindicator-new)
- [ποΈ Comprehensive Example](#οΈ-comprehensive-example)
- [π οΈ Utilities](#οΈ-utilities)
- [FloeColors](#floecolors)
- [FloeFont](#floefont)
- [FloeSpacing](#floespacing)
- [FloeShadow](#floeshadow)
- [πΊοΈ Roadmap](#οΈ-roadmap)
- [π¨ Theming](#-theming)
- [π License](#-license)
- [π Acknowledgments](#-acknowledgments)
---
## β¨ Features
- **π¨ Consistent Design System** - Unified colors, typography, spacing, and shadows
- **π± Cross-Platform** - Works seamlessly on iOS and macOS
- **π Perfect Dark Mode** - β
**Complete** - All components tested and beautiful in both light and dark modes
- **βΏ Accessibility First** - Built-in VoiceOver, Dynamic Type, and comprehensive accessibility support
- **ποΈ Advanced Architecture** - Result builders, preference keys, haptic feedback, and sophisticated animations
- **π§ Highly Customizable** - Override any aspect while maintaining design consistency
- **β‘ Performance Optimized** - Efficient SwiftUI implementation with smooth 60fps animations
- **π¦ Zero Dependencies** - Pure SwiftUI implementation with no external dependencies
- **π― Production Ready** - Battle-tested components with proper error handling and edge cases
---
## π Installation
### Swift Package Manager
Add FloeKit to your project through Xcode:
1. File β Add Package Dependencies
2. Enter package URL: `https://github.com/nemanjavlahovic/FloeKit`
3. Select version and add to target
Or add to your `Package.swift`:
```swift
dependencies: [
.package(url: "https://github.com/nemanjavlahovic/FloeKit", from: "0.3.0")
]
```
---
## π§± Components
### FloeButton
Soft, elevated buttons with multiple sizes, loading states, and icon support.

```swift
import FloeKit
// Basic button
FloeButton("Get Started") {
// Action
}
// Button with icon and custom styling
// Note: Parameters can be specified in any order using named parameters
FloeButton("Save",
size: .large,
backgroundColor: .blue,
textColor: .white,
icon: Image(systemName: "checkmark")) {
// Save action
}
// Loading state
FloeButton("Processing...", isLoading: true) {
// Action
}
```
**Sizes:** `.small`, `.medium`, `.large`
**Features:** Loading states, icons, custom colors, accessibility support
---
### FloeTextField
Elegant text input with focus states, icons, validation, and character limits.

```swift
@State private var email = ""
@State private var password = ""
@State private var bio = ""
// Basic text field
FloeTextField(text: $email, placeholder: "Email address")
// With icons and validation
FloeTextField(
text: $email,
placeholder: "Enter email",
leadingIcon: Image(systemName: "envelope"),
errorMessage: "Invalid email format"
)
// Secure field
FloeTextField(
text: $password,
placeholder: "Password",
leadingIcon: Image(systemName: "lock"),
isSecure: true
)
// With character limit
FloeTextField(
text: $bio,
placeholder: "Bio",
characterLimit: 150
)
```
**Features:** Icons, secure input, validation, character limits, focus states
---
### FloeCard
Clean, elevated containers with consistent shadows and padding.

```swift
FloeCard {
VStack {
Text("Card Title")
.floeFont(.headline)
Text("Card content goes here")
.floeFont(.body)
}
}
// Custom styling
FloeCard(backgroundColor: .blue.opacity(0.1),
shadowStyle: .elevated,
padding: .spacious) {
// Content
}
```
**Features:** Customizable shadows, padding presets, border support
---
### FloeAvatar
Elegant, customizable avatar components with status indicators and grouping support.

```swift
// Basic avatars
FloeAvatar.initials("JD")
FloeAvatar.icon("person.fill")
FloeAvatar.placeholder()
// With image
FloeAvatar(image: Image("user-photo"))
// Different sizes
FloeAvatar.initials("SM", size: .small)
FloeAvatar.initials("LG", size: .large)
FloeAvatar.initials("XL", size: .extraLarge)
// With status indicators
FloeAvatar.online(initials: "ON")
FloeAvatar(initials: "AW", statusIndicator: .away)
FloeAvatar(initials: "BY", statusIndicator: .busy)
FloeAvatar(initials: "CT", statusIndicator: .custom(.purple))
// Custom styling
FloeAvatar(
initials: "VIP",
backgroundColor: .black,
foregroundColor: .yellow,
borderColor: .yellow,
borderWidth: 2,
shadowStyle: .elevated
)
// Interactive avatars
FloeAvatar.initials("TAP") {
print("Avatar tapped!")
}
```
**Grouped Avatars:**
```swift
// Stacked avatars with overlap
FloeAvatarGroup(
avatars: [avatar1, avatar2, avatar3],
style: .stacked,
maxVisible: 3
)
// Grid layout
FloeAvatarGroup(
avatars: avatarArray,
style: .grid(columns: 2)
)
```
**Sizes:** `.small`, `.medium`, `.large`, `.extraLarge`
**Status:** Online, offline, away, busy, custom colors
**Features:** Images, initials, SF Symbols, borders, shadows, tap actions, grouping
---
### FloeToast *(New)*
Lightweight, animated toast notifications with swipe-to-dismiss and customizable styles.
```swift
@StateObject private var toastManager = FloeToastManager()
// Basic usage with convenience methods
.floeToast(FloeToast.success("Success!", message: "Operation completed"))
.floeToast(FloeToast.error("Error!", message: "Something went wrong"))
.floeToast(FloeToast.warning("Warning!", message: "Please check your input"))
.floeToast(FloeToast.info("Info", message: "New update available"))
// Custom toast with action
FloeToast("Custom Toast",
message: "With action button",
style: .custom(backgroundColor: .purple,
foregroundColor: .white,
icon: Image(systemName: "star.fill")),
actionTitle: "Action") {
// Action handler
}
// Using Toast Manager
toastManager.show(FloeToast.success("Saved successfully!"))
// Advanced configuration
FloeToast("Upload Complete",
message: "Your file has been uploaded",
style: .success,
position: .bottom,
duration: 5.0,
actionTitle: "View") {
// View file action
} onDismiss: {
print("Toast dismissed")
}
```
**Styles:** Success, warning, error, info, custom
**Positions:** Top, bottom
**Features:** Auto-dismiss, swipe gestures, action buttons, custom styling, animations
---
### FloeTabBar *(New)*
Modern floating tab bar with smooth animations and flexible configuration.


```swift
// Define tabs
let tabs = [
FloeTabBar.Tab.systemIcon(id: "home", title: "Home",
systemName: "house", selectedSystemName: "house.fill"),
FloeTabBar.Tab.systemIcon(id: "search", title: "Search",
systemName: "magnifyingglass", badge: "3"),
FloeTabBar.Tab.systemIcon(id: "favorites", title: "Favorites",
systemName: "heart", selectedSystemName: "heart.fill"),
FloeTabBar.Tab.systemIcon(id: "profile", title: "Profile",
systemName: "person", selectedSystemName: "person.fill")
]
// Basic tab bar
@State private var selectedTab = "home"
FloeTabBar(
tabs: tabs,
selectedTabId: selectedTab,
onTabSelected: { selectedTab = $0 }
)
// Floating style with central action
FloeTabBar(
tabs: tabs,
selectedTabId: selectedTab,
onTabSelected: { selectedTab = $0 },
style: .floating,
indicatorStyle: .pill,
centralAction: { print("Add new item") },
centralActionIcon: Image(systemName: "plus.circle.fill")
)
// Scrollable for many tabs
FloeTabBar(
tabs: manyTabs,
selectedTabId: selectedTab,
onTabSelected: { selectedTab = $0 },
isScrollable: true
)
// Complete tab bar controller
FloeTabBarController(
tabs: tabs,
initialSelection: "home",
style: .floating
) { selectedTab in
// Content for each tab
switch selectedTab {
case "home": HomeView()
case "search": SearchView()
case "favorites": FavoritesView()
case "profile": ProfileView()
default: EmptyView()
}
}
```
**Styles:** Floating, attached, minimal
**Indicators:** Pill, underline, background, none
**Features:** Badges, central action button, scrollable tabs, animations, custom icons
**Result Builder Syntax:**
```swift
// Declarative tab creation with @TabBuilder
FloeTabBar(
selectedTabId: selectedTab,
onTabSelected: { selectedTab = $0 },
style: .floating,
indicatorStyle: .pill
) {
FloeTabBar.Tab.systemIcon(id: "home", title: "Home", systemName: "house")
FloeTabBar.Tab.systemIcon(id: "search", title: "Search", systemName: "magnifyingglass")
FloeTabBar.Tab.systemIcon(id: "favorites", title: "Favorites", systemName: "heart")
FloeTabBar.Tab.systemIcon(id: "profile", title: "Profile", systemName: "person")
}
```
---
### FloeSlider *(New)*
Customizable slider with haptic feedback, value labels, and both horizontal/vertical orientations.
```swift
@State private var volume: Double = 50
@State private var brightness: Double = 0.7
// Basic slider
FloeSlider(value: $volume, in: 0...100, showLabels: .value)
// Percentage slider with convenience method
FloeSlider.percentage(value: $volume, showLabels: true)
// Volume-style slider (0-1)
FloeSlider.volume(value: $brightness)
// Custom range with steps
FloeSlider(
value: $rating,
in: 0...5,
step: 0.5,
showLabels: .value,
showMinMax: true
)
// Vertical slider
FloeSlider(
value: $volume,
in: 0...100,
orientation: .vertical,
showLabels: .percentage
)
.frame(height: 200)
// Custom styling
FloeSlider(
value: $temperature,
in: 16...30,
showLabels: .custom({ "\(Int($0))Β°C" }),
fillColor: .orange,
thumbColor: .red,
enableHaptics: true
)
```
**Orientations:** Horizontal, vertical
**Label Styles:** None, value, percentage, custom formatter
**Features:** Haptic feedback, range indicators, step values, custom styling, accessibility
---
### FloeTextView *(New)*
Rich text display and editing component with expansion controls and character limits.

```swift
@State private var editableText = ""
@State private var limitedText = ""
// Basic editable text view
FloeTextView(
text: $editableText,
placeholder: "Enter your thoughts...",
size: .medium
)
// Read-only with expansion
FloeTextView.readOnly(
text: "Long text content that can be expanded...",
expansionStyle: .readMore(previewLines: 2)
)
// With character limit
FloeTextView.withCharacterLimit(
text: $limitedText,
placeholder: "Bio (max 100 characters)",
characterLimit: 100,
size: .small
)
// Attributed text with rich formatting
FloeTextView.attributedText(
attributedString,
size: .medium,
expansionStyle: .readMore(previewLines: 3)
)
```
**Sizes:** `.small`, `.medium`, `.large`
**Expansion Styles:** Read more/less, character limits, custom
**Features:** Rich text support, smooth animations, character counting, accessibility
---
### FloeProgressIndicator *(New)*
Versatile progress indicators with linear and circular styles, supporting both determinate and indeterminate states.

```swift
@State private var progress: Double = 0.65
// Linear progress indicators
FloeProgressIndicator(
progress: progress,
style: .linear,
size: .medium,
showPercentage: true
)
// Circular progress indicators
FloeProgressIndicator(
progress: 0.75,
style: .circular,
size: .large,
showPercentage: true
)
// Indeterminate loading
FloeProgressIndicator.indeterminate(
style: .circular,
size: .medium,
color: .blue
)
// State-based indicators
FloeProgressIndicator.loading(style: .circular, size: .medium)
FloeProgressIndicator.success(style: .circular, size: .medium)
FloeProgressIndicator.error(style: .circular, size: .medium)
// Custom styling
FloeProgressIndicator(
progress: progress,
style: .linear,
size: .large,
color: .purple,
backgroundColor: .gray.opacity(0.2),
showPercentage: true
)
```
**Styles:** Linear, circular
**States:** Determinate, indeterminate, loading, success, error
**Sizes:** `.small`, `.medium`, `.large`
**Features:** Smooth animations, custom colors, percentage display, accessibility
---
## ποΈ Comprehensive Example
Here's how FloeKit components work together in a real application:
```swift
import SwiftUI
import FloeKit
struct ProfileView: View {
@State private var name = ""
@State private var bio = ""
@State private var selectedTab = "profile"
@State private var showSuccessToast = false
var body: some View {
FloeTabBarController(
initialSelection: "profile",
style: .floating
) {
FloeTabBar.Tab.systemIcon(id: "profile", title: "Profile", systemName: "person")
FloeTabBar.Tab.systemIcon(id: "settings", title: "Settings", systemName: "gear")
} content: { selectedTab in
ScrollView {
VStack(spacing: FloeSpacing.Size.lg.value) {
// Avatar Section
FloeCard {
VStack(spacing: FloeSpacing.Size.md.value) {
FloeAvatar.initials("JD", size: .extraLarge)
Text("John Doe")
.floeFont(.headline)
}
.frame(maxWidth: .infinity)
}
// Form Section
FloeCard(padding: .comfortable) {
VStack(spacing: FloeSpacing.Size.md.value) {
FloeTextField(
text: $name,
placeholder: "Full Name",
leadingIcon: Image(systemName: "person.fill")
)
FloeTextView.withCharacterLimit(
text: $bio,
placeholder: "Tell us about yourself...",
characterLimit: 150,
size: .medium
)
FloeButton("Save Profile",
size: .large,
backgroundColor: FloeColors.primary,
textColor: .white) {
showSuccessToast = true
}
}
}
// Progress Section
FloeCard {
VStack(alignment: .leading, spacing: FloeSpacing.Size.sm.value) {
Text("Profile Completion")
.floeFont(.headline)
FloeProgressIndicator(
progress: 0.75,
style: .linear,
size: .medium,
showPercentage: true
)
}
}
}
.floePadding(.comfortable)
}
.floeToast(showSuccessToast ?
FloeToast.success("Profile Updated!",
message: "Your changes have been saved") {
showSuccessToast = false
} : nil
)
}
}
}
```
**This example demonstrates:**
- **FloeTabBarController** with multiple screens
- **FloeCard** for clean content organization
- **FloeAvatar** for user representation
- **FloeTextField** with icons for form input
- **FloeTextView** with character limits for longer text
- **FloeButton** for primary actions
- **FloeProgressIndicator** for status display
- **FloeToast** for user feedback
- **FloeSpacing** and **FloeFont** for consistent styling
---
## π οΈ Utilities
### FloeColors
Adaptive color palette with seamless light/dark mode support.
```swift
// Primary semantic colors
.foregroundColor(FloeColors.primary) // Main brand color
.backgroundColor(FloeColors.secondary) // Secondary brand color
.foregroundColor(FloeColors.accent) // Accent highlights
.foregroundColor(FloeColors.error) // Error states
// Surface colors
.backgroundColor(FloeColors.background) // Main background
.backgroundColor(FloeColors.surface) // Card/component backgrounds
// Neutral scale for subtle elements
.foregroundColor(FloeColors.neutral0) // Pure contrast
.foregroundColor(FloeColors.neutral10) // High contrast text
.foregroundColor(FloeColors.neutral20) // Medium contrast borders
.foregroundColor(FloeColors.neutral30) // Low contrast dividers
.foregroundColor(FloeColors.neutral40) // Subtle text
.foregroundColor(FloeColors.neutral90) // Very subtle backgrounds
// State colors
.foregroundColor(FloeColors.success) // Success feedback
.foregroundColor(FloeColors.warning) // Warning states
```
**β
All colors automatically adapt to light/dark mode**
**β
Consistent contrast ratios for accessibility**
**β
Can be overridden via color assets for custom theming**
---
### FloeFont
Typography system with semantic font styles.
```swift
Text("Headline")
.floeFont(.headline)
Text("Body text")
.floeFont(.body)
// Or with custom size and weight
Text("Custom")
.floeFont(size: .xl, weight: .bold)
// Available styles: .body, .caption, .button, .title, .headline, .subheadline
// Available sizes: .xs, .sm, .base, .lg, .xl, .xl2, .xl3, .xl4
```
---
### FloeSpacing
Consistent spacing and padding system.
```swift
// Use spacing tokens
VStack(spacing: FloeSpacing.Size.lg.value) {
// Content
}
// Apply semantic padding
SomeView()
.floePadding(.card) // Standard card padding
.floePadding(.section) // Section container padding
.floePadding(.comfortable) // Comfortable all-around padding
.floePadding(.spacious) // Spacious padding
.floePadding(.generous) // Generous padding
// Custom spacing
SomeView()
.floePadding(.vertical, .lg)
.floePadding(.horizontal, .xl)
```
---
### FloeShadow
Consistent shadow system with automatic dark mode adaptation.
```swift
// Apply semantic shadows
RoundedRectangle(cornerRadius: 12)
.floeShadow(.soft) // Subtle shadow
.floeShadow(.medium) // Standard shadow
.floeShadow(.elevated) // Strong shadow
// Available styles: .none, .subtle, .soft, .medium, .elevated
```
---
## πΊοΈ Roadmap
### ποΈ FloeStepper *(Next Phase)*
Custom stepper component with enhanced visual feedback.
- Smooth animations and haptic feedback
- Custom styling and button designs
- Long press for rapid changes
- Custom step values and ranges
### π
FloeDatePicker & FloeTimePicker *(Next Phase)*
Modern date and time selection components.
- Inline and compact picker styles
- Custom styling with FloeKit design language
- Range selection support
- Localization and timezone support
### π FloeSearchBar *(Next Phase)*
Enhanced search bar with modern styling and functionality.
- Animated search icon and clear button
- Search suggestions and recent searches
- Voice input support
- Custom filtering and debouncing
### π FloeList & FloeGrid *(Planned)*
Enhanced list and grid components with built-in styling.
- Pull-to-refresh and infinite scrolling
- Swipe actions and reordering
- Section headers with sticky behavior
- Loading states and empty state views
### π¨ FloeColorPicker *(Planned)*
Modern color selection component.
- Multiple picker styles (wheel, palette, sliders)
- Custom color palettes and recent colors
- Hex, RGB, HSL input support
- Eyedropper functionality
### π FloeChart *(Planned)*
Simple charting components for basic data visualization.
- Line, bar, and pie chart support
- Animated data updates
- Interactive tooltips and legends
- Customizable colors and styling
---
## π¨ Theming
FloeKit supports comprehensive theming through color asset overrides:
1. Add a `Colors.xcassets` to your app
2. Create color sets with FloeKit's color names:
- `FloePrimary`, `FloeSecondary`, `FloeAccent`
- `FloeBackground`, `FloeSurface`
- `FloeNeutral0`, `FloeNeutral10`, `FloeNeutral20`, `FloeNeutral30`, `FloeNeutral40`, `FloeNeutral90`
3. FloeKit will automatically use your custom colors
---
## π License
FloeKit is available under the MIT license. See [LICENSE](LICENSE) for details.
---
## π Acknowledgments
Inspired by modern design systems and the SwiftUI community's best practices.
---