Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -271,3 +271,42 @@ provided below is an organized table of W3C HTML tags and their equivalent Slips
[`<mtable>`](https://www.w3.org/TR/MathML3/chapter3.html#presm.mtable) | ``MTable``
[`<mtr>`](https://www.w3.org/TR/MathML3/chapter3.html#presm.mtr) | ``MTr``
[`<mtd>`](https://www.w3.org/TR/MathML3/chapter3.html#presm.mtd) | ``MTd``

## The global attributes of Slipstream

Modeling after [the W3C specification](https://html.spec.whatwg.org/multipage/dom.html#global-attributes),
provided below is an organized table of W3C global HTML attributes and their equivalent Slipstream view modifiers.

### Global attributes

W3C attribute | Slipstream modifier | Notes
:-------------|:-------------------|:------
[`accesskey`](https://html.spec.whatwg.org/multipage/interaction.html#the-accesskey-attribute) | ``keyboardShortcut(_:)`` | Specifies a keyboard shortcut to activate or focus the element
[`autocapitalize`](https://html.spec.whatwg.org/multipage/interaction.html#attr-autocapitalize) | ``autocapitalize(_:)`` | Controls whether and how text input is automatically capitalized
[`autofocus`](https://html.spec.whatwg.org/multipage/interaction.html#attr-fe-autofocus) | ``autofocus(_:)`` | Indicates that the element should be focused on page load
`class` | ``className(_:)`` | Adds classes to the element. Use TailwindCSS modifiers for styling
[`contenteditable`](https://html.spec.whatwg.org/multipage/interaction.html#attr-contenteditable) | ``contenteditable(_:)`` | Indicates whether the element's content is editable
[`data-*`](https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes) | ``data(_:)`` | Sets custom data attributes on the view
[`dir`](https://html.spec.whatwg.org/multipage/dom.html#attr-dir) | ``direction(_:)`` | Specifies the element's text directionality
[`draggable`](https://html.spec.whatwg.org/multipage/dnd.html#attr-draggable) | ``draggable(_:)`` | Indicates whether the element can be dragged
[`enterkeyhint`](https://html.spec.whatwg.org/multipage/interaction.html#attr-enterkeyhint) | ``submitLabel(_:)`` | Hints at the action label for the enter key on virtual keyboards
[`hidden`](https://html.spec.whatwg.org/multipage/interaction.html#attr-hidden) | ``hidden(_:)`` | Sets the HTML hidden attribute (different from TailwindCSS hidden())
`id` | ``id(_:)`` | Sets the element's unique identifier
[`inert`](https://html.spec.whatwg.org/multipage/interaction.html#the-inert-attribute) | ``allowsHitTesting(_:)`` | Controls whether the element can receive user interaction (inverted logic)
[`inputmode`](https://html.spec.whatwg.org/multipage/interaction.html#attr-inputmode) | ``keyboardType(_:)`` | Sets the keyboard type for text input
[`is`](https://html.spec.whatwg.org/multipage/custom-elements.html#attr-is) | ``customElement(_:)`` | Specifies the name of a custom element
[`itemid`](https://html.spec.whatwg.org/multipage/microdata.html#attr-itemid) | ``itemID(_:)`` | The globally unique identifier of a microdata item
[`itemprop`](https://html.spec.whatwg.org/multipage/microdata.html#names:-the-itemprop-attribute) | ``itemProp(_:)`` | Used to add properties to a microdata item
[`itemref`](https://html.spec.whatwg.org/multipage/microdata.html#attr-itemref) | ``itemRef(_:)`` | Associates non-descendant properties with a microdata item
[`itemscope`](https://html.spec.whatwg.org/multipage/microdata.html#attr-itemscope) | ``itemScope(_:)`` | Creates a new microdata item
[`itemtype`](https://html.spec.whatwg.org/multipage/microdata.html#attr-itemtype) | ``itemType(_:)`` | Specifies the vocabulary URL for a microdata item
[`lang`](https://html.spec.whatwg.org/multipage/dom.html#attr-lang) | ``language(_:)`` | Sets the primary language for the view's contents
[`nonce`](https://html.spec.whatwg.org/multipage/urls-and-fetching.html#attr-nonce) | ``nonce(_:)`` | A cryptographic nonce used by Content Security Policy
[`popover`](https://html.spec.whatwg.org/multipage/popover.html#attr-popover) | ``popover(_:)`` | Indicates that the element is a popover element
`slot` | ``slot(_:)`` | Assigns a slot in a shadow DOM shadow tree
[`spellcheck`](https://html.spec.whatwg.org/multipage/interaction.html#attr-spellcheck) | ``spellcheck(_:)`` | Specifies whether the element may be checked for spelling errors
[`style`](https://html.spec.whatwg.org/multipage/dom.html#attr-style) | ``inlineStyle(_:)`` | Contains CSS styling declarations. Prefer TailwindCSS modifiers when possible
[`tabindex`](https://html.spec.whatwg.org/multipage/interaction.html#attr-tabindex) | ``tabIndex(_:)`` or ``focusable()`` | Controls focus and keyboard navigation
[`title`](https://html.spec.whatwg.org/multipage/dom.html#attr-title) | ``tooltip(_:)`` | Advisory information, typically shown as a tooltip
[`translate`](https://html.spec.whatwg.org/multipage/dom.html#attr-translate) | ``translatable(_:)`` | Specifies whether content should be translated
[`writingsuggestions`](https://html.spec.whatwg.org/multipage/interaction.html#attr-writingsuggestions) | ``writingSuggestions(_:)`` | Controls whether browser-provided writing suggestions should be offered
75 changes: 75 additions & 0 deletions Sources/Slipstream/Fundamentals/AttributeModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,65 @@ public struct AttributeModifier<T: View>: ViewModifier {

/// A W3C global attribute, as defined in [3.2.3 Global attributes](https://html.spec.whatwg.org/multipage/dom.html#global-attributes).
public enum GlobalAttribute: String {
/// Specifies a keyboard shortcut to activate or focus the element.
case accesskey

/// Controls whether and how text input is automatically capitalized.
case autocapitalize

/// Indicates that the element should be focused on page load.
case autofocus

/// The class attribute is most commonly used by stylesheets to apply styles
/// to a view.
case `class`

/// Indicates whether the element's content is editable.
case contenteditable

/// Specifies the element's text directionality.
case dir

/// Indicates whether the element can be dragged.
case draggable

/// Hints at the type of data that might be entered by the user while editing the element or its contents.
case enterkeyhint

/// Indicates that the element is not yet, or is no longer, relevant.
case hidden

/// The id attribute specifies its element's unique identifier (ID).
///
/// There are no other restrictions on what form an ID can take; in particular,
/// IDs can consist of just digits, start with a digit, start with an
/// underscore, consist of just punctuation, etc.
case id

/// Indicates that the element and its descendants should be made non-interactive.
case inert

/// Hints at the type of data that might be entered by the user while editing the element.
case inputmode

/// Specifies the name of a custom element.
case `is`

/// The globally unique identifier of an item.
case itemid

/// Used to add properties to an item.
case itemprop

/// Properties that are not descendants of an element can be associated with the item using this attribute.
case itemref

/// Creates a new item, a group of name-value pairs.
case itemscope

/// Specifies the URL of the vocabulary that will be used to define item properties.
case itemtype

/// The lang attribute specifies the primary language for the view's contents
/// and for any of the view's attributes that contain text. Its value must be a
/// valid [BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag),
Expand All @@ -50,6 +98,33 @@ public struct AttributeModifier<T: View>: ViewModifier {
/// - [Common primary language tags](https://en.wikipedia.org/wiki/IETF_language_tag#List_of_common_primary_language_subtags)
/// - [Language Subtag Registry](https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry)
case lang

/// A cryptographic nonce used by Content Security Policy.
case nonce

/// Indicates that the element is a popover element.
case popover

/// Assigns a slot in a shadow DOM shadow tree to an element.
case slot

/// Specifies whether the element may be checked for spelling errors.
case spellcheck

/// Contains CSS styling declarations to be applied to the element.
case style

/// Specifies whether the element can be focused and whether/where it participates in sequential keyboard navigation.
case tabindex

/// Advisory information associated with the element.
case title

/// Specifies whether an element's attribute values and text content should be translated.
case translate

/// Controls whether browser-provided writing suggestions should be offered.
case writingsuggestions
}

/// Creates an attribute modifier that will set `attribute` to `value` on any modified views.
Expand Down
23 changes: 23 additions & 0 deletions Sources/Slipstream/W3C/Attributes/View+accesskey.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
extension View {
/// Specifies a keyboard shortcut to activate or focus the element.
///
/// The accesskey attribute's value is used to generate a keyboard shortcut that
/// activates or focuses the element. The exact behavior depends on the browser and platform.
///
/// ```swift
/// Button("Save") {
/// // Save action
/// }
/// .keyboardShortcut("s")
/// ```
///
/// - Parameter key: A single character that will be used as the keyboard shortcut.
/// The exact key combination varies by browser and platform (e.g., Alt+key on Windows,
/// Control+Option+key on macOS).
///
/// - SeeAlso: W3C [`accesskey`](https://html.spec.whatwg.org/multipage/interaction.html#the-accesskey-attribute) specification.
@available(iOS 17.0, macOS 14.0, *)
public func keyboardShortcut(_ key: String) -> some View {
return modifier(AttributeModifier(.accesskey, value: key))
}
}
32 changes: 32 additions & 0 deletions Sources/Slipstream/W3C/Attributes/View+autocapitalize.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/// The autocapitalize attribute controls whether and how text input is automatically capitalized.
@available(iOS 17.0, macOS 14.0, *)
public enum Autocapitalize: String {
/// No automatic capitalization.
case none
/// Capitalize the first letter of each sentence.
case sentences
/// Capitalize the first letter of each word.
case words
/// Capitalize all characters.
case characters
}

extension View {
/// Controls whether and how text input is automatically capitalized.
///
/// The autocapitalize attribute is particularly useful for mobile devices where the system
/// keyboard can automatically capitalize text based on the specified behavior.
///
/// ```swift
/// TextField("Name", type: .text)
/// .autocapitalize(.words)
/// ```
///
/// - Parameter mode: The autocapitalization behavior to apply.
///
/// - SeeAlso: W3C [`autocapitalize`](https://html.spec.whatwg.org/multipage/interaction.html#attr-autocapitalize) specification.
@available(iOS 17.0, macOS 14.0, *)
public func autocapitalize(_ mode: Autocapitalize) -> some View {
return modifier(AttributeModifier(.autocapitalize, value: mode.rawValue))
}
}
20 changes: 20 additions & 0 deletions Sources/Slipstream/W3C/Attributes/View+autofocus.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
extension View {
/// Indicates that the element should be focused when the page loads.
///
/// Only one element in the document should have the autofocus attribute. If applied
/// to multiple elements, the first one in document order will receive focus.
///
/// ```swift
/// TextField("Search", type: .search)
/// .autofocus()
/// ```
///
/// - Parameter condition: A Boolean value that determines whether the element should
/// receive focus on page load. Defaults to true.
///
/// - SeeAlso: W3C [`autofocus`](https://html.spec.whatwg.org/multipage/interaction.html#attr-fe-autofocus) specification.
@available(iOS 17.0, macOS 14.0, *)
public func autofocus(_ condition: Bool = true) -> some View {
return modifier(ConditionalAttributeModifier("autofocus", condition: condition))
}
}
40 changes: 40 additions & 0 deletions Sources/Slipstream/W3C/Attributes/View+contenteditable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/// The contenteditable attribute indicates whether the element's content is editable.
@available(iOS 17.0, macOS 14.0, *)
public enum Contenteditable: String {
/// The element is editable.
case `true`
/// The element is not editable.
case `false`
/// The element inherits the contenteditable state from its parent.
case inherit = "inherit"
}

extension View {
/// Indicates whether the element's content is editable.
///
/// The contenteditable attribute makes an element's content editable by the user.
/// This is commonly used to create rich text editors and inline editing experiences.
///
/// ```swift
/// Div {
/// Text("Edit this text")
/// }
/// .contenteditable(.true)
/// ```
///
/// - Parameter value: The editability state of the element.
///
/// - SeeAlso: W3C [`contenteditable`](https://html.spec.whatwg.org/multipage/interaction.html#attr-contenteditable) specification.
@available(iOS 17.0, macOS 14.0, *)
public func contenteditable(_ value: Contenteditable) -> some View {
return modifier(AttributeModifier(.contenteditable, value: value.rawValue))
}

/// Indicates whether the element's content is editable.
///
/// - Parameter condition: A Boolean value that determines whether the element is editable.
@available(iOS 17.0, macOS 14.0, *)
public func contenteditable(_ condition: Bool) -> some View {
return modifier(AttributeModifier(.contenteditable, value: condition ? "true" : "false"))
}
}
33 changes: 33 additions & 0 deletions Sources/Slipstream/W3C/Attributes/View+dir.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/// The dir attribute specifies the element's text directionality.
@available(iOS 17.0, macOS 14.0, *)
public enum TextDirection: String {
/// Left-to-right text direction.
case ltr
/// Right-to-left text direction.
case rtl
/// Automatic text direction based on content.
case auto
}

extension View {
/// Specifies the element's text directionality.
///
/// The dir attribute controls the direction in which text is rendered. This is
/// particularly important for languages like Arabic and Hebrew that are written
/// right-to-left.
///
/// ```swift
/// Div {
/// Text("مرحبا بك")
/// }
/// .direction(.rtl)
/// ```
///
/// - Parameter direction: The text direction for the element.
///
/// - SeeAlso: W3C [`dir`](https://html.spec.whatwg.org/multipage/dom.html#attr-dir) specification.
@available(iOS 17.0, macOS 14.0, *)
public func direction(_ direction: TextDirection) -> some View {
return modifier(AttributeModifier(.dir, value: direction.rawValue))
}
}
23 changes: 23 additions & 0 deletions Sources/Slipstream/W3C/Attributes/View+draggable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
extension View {
/// Indicates whether the element can be dragged.
///
/// The draggable attribute controls whether an element can be dragged using the
/// HTML Drag and Drop API. This is commonly used for implementing drag-and-drop
/// interfaces.
///
/// ```swift
/// Div {
/// Text("Drag me")
/// }
/// .draggable()
/// ```
///
/// - Parameter condition: A Boolean value that determines whether the element can be dragged.
/// Defaults to true.
///
/// - SeeAlso: W3C [`draggable`](https://html.spec.whatwg.org/multipage/dnd.html#attr-draggable) specification.
@available(iOS 17.0, macOS 14.0, *)
public func draggable(_ condition: Bool = true) -> some View {
return modifier(AttributeModifier(.draggable, value: condition ? "true" : "false"))
}
}
45 changes: 45 additions & 0 deletions Sources/Slipstream/W3C/Attributes/View+enterkeyhint.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/// The enterkeyhint attribute hints at the action label or icon for the enter key
/// on virtual keyboards.
@available(iOS 17.0, macOS 14.0, *)
public enum EnterKeyHint: String {
/// The user agent should present a cue for the action 'enter', typically inserting a new line.
case enter
/// The user agent should present a cue for the action 'done', typically meaning there is
/// nothing more to input and the input method editor (IME) will be closed.
case done
/// The user agent should present a cue for the action 'go', typically meaning to take the
/// user to the target of the text they typed.
case go
/// The user agent should present a cue for the action 'next', typically taking the user to
/// the next field that will accept text.
case next
/// The user agent should present a cue for the action 'previous', typically taking the user
/// to the previous field that will accept text.
case previous
/// The user agent should present a cue for the action 'search', typically taking the user
/// to the results of searching for the text they have typed.
case search
/// The user agent should present a cue for the action 'send', typically delivering the text
/// to its target.
case send
}

extension View {
/// Hints at the action label or icon to present for the enter key on virtual keyboards.
///
/// The submitLabel modifier is particularly useful on mobile devices where the virtual
/// keyboard can display different labels on the enter key based on the expected action.
///
/// ```swift
/// TextField("Search", type: .search)
/// .submitLabel(.search)
/// ```
///
/// - Parameter label: The label for the enter key presentation.
///
/// - SeeAlso: W3C [`enterkeyhint`](https://html.spec.whatwg.org/multipage/interaction.html#attr-enterkeyhint) specification.
@available(iOS 17.0, macOS 14.0, *)
public func submitLabel(_ label: EnterKeyHint) -> some View {
return modifier(AttributeModifier(.enterkeyhint, value: label.rawValue))
}
}
32 changes: 32 additions & 0 deletions Sources/Slipstream/W3C/Attributes/View+hidden.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/// The hidden attribute indicates that the element is not yet, or is no longer, relevant.
@available(iOS 17.0, macOS 14.0, *)
public enum HiddenState: String {
/// The element is hidden in all rendering modes.
case hidden = ""
/// The element is hidden but remains in the accessibility tree until it is found.
case untilFound = "until-found"
}

extension View {
/// Indicates that the element is not yet, or is no longer, relevant.
///
/// Sets the HTML `hidden` attribute to semantically mark content as not relevant.
/// This is different from the TailwindCSS `hidden()` modifier which uses CSS to
/// visually hide elements.
///
/// ```swift
/// Div {
/// Text("This content is hidden")
/// }
/// .hidden(.hidden)
/// ```
///
/// - Parameter state: The hidden state of the element.
///
/// - SeeAlso: W3C [`hidden`](https://html.spec.whatwg.org/multipage/interaction.html#attr-hidden) specification.
@available(iOS 17.0, macOS 14.0, *)
public func hidden(_ state: HiddenState) -> some View {
return modifier(AttributeModifier(.hidden, value: state.rawValue))
}
}

Loading