Swift DSL for writing slide decks in Xcode
✨ DeckUI
DeckUI is a Swift DSL (domain specific language) for writing slide decks in Xcode. It allows for quick creation of slides and content in a language and environment you are familiar with.
But why?
Well, I made this because:
- I was bored on an airplane
- Wanted to use this as a demo for future conference talk on Swift DSLs
- Need something more customizable than markdown for writing slide decks and more codey than Keynote
? Watch Introducing DeckUI – Write slide decks in Swift on my YouTube channel for more explaination and full demo
✨ Features
- Create slide decks in pure Swift code
- Decks are presented in SwiftUI with
Presenter
- Build decks without knowing any SwiftUI
- With
Deck
,Slide
,Title
,Words
,Bullets
,Media
,Columns
- With
- Use
RawView
to drop any SwiftUI view- Fully interactable and great for demos
- Display code with
Code
- Use up and down arrows to highlight lines of code as your talking about them
? Future Features
- Support iOS and maybe tvOS
- Fix bug with
Media
remote image loading and slide transitions - Animations within a slide
- Support videos on
Media
- More customization on
Words
- Nesting of
Bullets
- Syntax highlighting for
Code
- Documentation
- More examples
Simple Demo
import SwiftUI
import DeckUI
struct ContentView: View {
var body: some View {
Presenter(deck: self.deck)
}
}
extension ContentView {
var deck: Deck {
Deck(title: "SomeConf 2023") {
Slide(alignment: .center) {
Title("Welcome to DeckUI")
}
Slide {
Title("Quick Demo")
Columns {
Column {
Bullets {
Words("Bullets")
Words("Words")
Words("Images")
Words("Columns")
}
}
Column {
Media(.remoteImage(URL(string: "https://www.fillmurray.com/g/200/300")!))
}
}
}
}
}
}
Screen.Recording.2022-09-08.at.12.40.41.AM.mov
? Installing
Swift Package Manager
- File > Swift Packages > Add Package Dependency
- Add
https://github.com/joshdholtz/DeckUI.git
- Select “Up to Next Major” with “1.0.0”
? Getting Started
There are no official “Getting Started” docs yet ? But look at…
- Demo app for usage
- Sources/DeckUI/DSL for how the
Deck
,Slide
, and all slide components are built - Sources/DeckUI/Views for how
Presenter
is built
? Documentation
100% not documented yet but I’ll get there ?♂️
? Performance
Probably bad and never production ready ? Please only use DeckUI for a single presentation and never at any scale.
?? Contributing
Yes please! I’m happy to discuss issues and review/merge pull requests ? I will do my best to get to the but I am a dad, work at RevenueCat, and the lead maintainer of fastlane so I might not respond right away.
? Examples
Slide
Slide
can be used without any parameters but can be given a custom alignment
, padding
, and theme
.
Slide {
// Content
}
Slide(alignment: .center, padding: 80, theme: .white) {
// Content
}
Title
Title
can be used by itself or with an optional subtitle
. It was real similar to Words
but larger.
Slide(alignment: .center) {
Title("Introducing...")
}
Slide {
Title("Introduction", subtitle: "What is it?")
// Content
}
Words
Words
are similar to what a textbox would be in Keynote, PowerPoint, or Google Slides. There will eventually be more style configurations for words.
Slide(alignment: .center) {
Title("Center alignment")
Words("Slides can be center aligned")
Words("And more words")
}
Bullets
Bullets
turns Words
into a list. It takes an optional style
parameter where you can choose between .bullets
and .dash
. Bullets
cannot be nested yet but soon™️.
Slide {
Title("Introduction", subtitle: "What is it?")
Bullets {
Words("A custom Swift DSL to make slide decks")
Words("Distributed as a Swift Package")
Words("Develop your slide deck in Xcode with Swift")
}
}
Slide {
Title("Introduction", subtitle: "What is it?")
Bullets(style: .dash) {
Words("A custom Swift DSL to make slide decks")
Words("Distributed as a Swift Package")
Words("Develop your slide deck in Xcode with Swift")
}
}
Media
Media
provides a few ways to display images from various source types. This will eventually support videos.
Slide {
Media(.assetImage("some-asset-name"))
Media(.bundleImage("some-file-name.jpg"))
Media(.remoteImage(URL(string: "http://placekitten.com/g/200/300"))!)
}
Columns
Columns
allow you to use one to infinte Column
s. Put other slide content in Column
.
Slide {
Title("Columns")
Columns {
Column {
// Content
}
Column {
// Content
}
}
}
Slide {
Title("Columns")
Columns {
Column {
// Content
}
Column {
// Content
}
Column {
// Content
}
Column {
// Content
}
}
}
Code
Code
is a super specifi version Words
. It will:
- Display text as monospace
- Scroll vertical if bigger than screen
- Highlight lines of code when up and down arrows are pressed
Slide {
Code("""
struct ContentView: View {
var body: some View {
Text("Hello slides")
}
}
""")
}
Slide {
Code("""
struct ContentView: View {
var body: some View {
Text("Hello slides")
}
}
""", , enableHighlight: false)
}
RawView
Drop any SwiftUI view inside of RawView
. Could be built-in SwiftUI views like Text
or Button
but can also be any custom SwiftUI view.
Slide {
RawView {
CounterView()
}
}
struct CounterView: View {
@State var count = 0
var body: some View {
Button {
self.count += 1
} label: {
Text("Press me - \(self.count)")
.font(.system(size: 60))
.padding(.horizontal, 40)
.padding(.vertical, 20)
.foregroundColor(.white)
.overlay(
RoundedRectangle(cornerRadius: 25)
.stroke(Color.white, lineWidth: 2)
)
}.buttonStyle(.plain)
}
}
Themes
A Theme
can be set in Presenter
or individually on Slide
. There are three default themes (.dark
, .black
, .white
) but feel free to use your own.
struct ContentView: View {
var body: some View {
Presenter(deck: self.deck, showCamera: true)
}
}
extension Theme {
public static let venonat: Theme = Theme(
background: Color(hex: "#624a7b"),
title: Foreground(
color: Color(hex: "#ff5a5a"),
font: Font.system(size: 80,
weight: .bold,
design: .default)
),
subtitle: Foreground(
color: Color(hex: "#a48bbd"),
font: Font.system(size: 50,
weight: .light,
design: .default).italic()
),
body: Foreground(
color: Color(hex: "#FFFFFF"),
font: Font.system(size: 50,
weight: .regular,
design: .default)
),
code: Foreground(
color: Color(hex: "#FFFFFF"),
font: Font.system(size: 26,
weight: .regular,
design: .monospaced)
),
codeHighlighted: (Color(hex: "#312952"), Foreground(
color: Color(hex: "#FFFFFF"),
font: Font.system(size: 26,
weight: .heavy,
design: .monospaced)
))
)
}