# Appetite UI documentation Appetite UI is a Figma UI kit for iOS and Android apps, built like a design system. One token source drives Apple and Material components in light and dark mode, and exports to SwiftUI, Jetpack Compose, Flutter and CSS. Every page of https://www.appetiteui.com/docs/introduction in one file, in rail order, after a short summary of the product. Generated at build from content/docs and lib/site.config.ts. The token values the docs previews draw are at https://www.appetiteui.com/tokens.json, as W3C DTCG. ## About the product - Version: 2.5, the release on sale. - Platforms: iOS and Android. Apple and Material conventions live in one Figma file, in light and dark mode. - Tokens: 589 variables in 6 collections, one W3C DTCG source that exports to SwiftUI, Jetpack Compose, Flutter and CSS. - Price: One payment, lifetime updates: Solo $79 for one designer, Team $149 for up to ten people in one organization, Enterprise on request (hi@appetiteui.com). No refunds: a read-only preview of the whole file comes first. - Terms: https://www.appetiteui.com/terms-and-conditions. License: https://www.appetiteui.com/license. - Read-only preview of the full file: https://www.figma.com/design/LLtujjM0lpAtPXA7MxJOin/Appetite-UI-%E2%9C%A6-2.5?node-id=10-597 - Contact: hi@appetiteui.com or https://www.appetiteui.com/contact, answered by the designer who builds the kit. ## Plans The same Figma file on every plan. Solo, Team and Enterprise open one file. The license sets how many people work in it. - App screens to start from: Finance, booking, fitness, social, AI and food flows, built from the same components. - Apple and Material 3 in one file: 20 Apple and 17 Material 3 pattern pages on the same tokens. - 589 variables in 6 collections: Light and dark color, type, spacing, radius and motion. - Token source and outputs: One W3C DTCG source, exported to SwiftUI, Jetpack Compose, Flutter and CSS. ### Solo, $79 (USD, paid once) One designer, unlimited projects. - Personal and client work, no project limit - Edit components, variables and styles for your brand - Share design files with clients and developers - Every future release ### Team, $149 (USD, paid once) Up to ten people on one shared system. - Everything in Solo - Ten people sharing the same source of truth - Shared library setup guidance - Direct support from the maker ### Enterprise (Quoted in writing) Several product teams on one private library. - Everything in Team - Unlimited users - A derived private library for your brand - Every future release Buy Solo or Team: https://appetiteui.lemonsqueezy.com/checkout/buy/f6a62afc-a2d5-43e2-aae5-1ca0e3417077. Enterprise: hi@appetiteui.com. Pricing page: https://www.appetiteui.com/pricing. --- --- title: Introduction description: Appetite UI is a Figma UI kit for iOS and Android apps, built like a design system: what it includes, what it covers and where it fits with Apple and Google. group: Get started source: https://www.appetiteui.com/docs/introduction dateModified: 2026-10-03 --- # Introduction Updated: October 3, 2026. Appetite UI is a Figma UI kit for iOS and Android apps, built like a design system. One token source drives Apple and Material components in light and dark mode, and exports to SwiftUI, Jetpack Compose, Flutter and CSS. Apple and Google publish the platform baseline; Appetite UI is the token layer that puts your brand on it. ## What is Appetite UI? Appetite UI is a Figma UI kit made only for iOS and Android apps and built like a design system. The components, the token system and the platform-aware native elements all run on Figma's own variables, so nothing needs a plugin, and every component value reads a token. ![A collage of app screens built from Appetite UI components: a blue finance home with balance, quick actions and recent transactions in the middle, with cards, chat, a task list and workout analytics on the left, and an inbox, a task detail and an unfolded iPhone Duo portfolio screen on the right.](https://www.appetiteui.com/images/docs-intro-screens.webp) ## Which platform features does the kit cover? iPhone Duo, the Dynamic Island, charts and tables, a Tasks app, Liquid Glass in three styles and a Focused state on the form controls. The table names each area and the page that explains it. | Area | What the kit holds | Read more | | --- | --- | --- | | iPhone Duo | Outer and inner display screens for 8 apps in light and dark, a vertical control rail and two Platform modes. | [iPhone Duo screens](https://www.appetiteui.com/docs/screens-iphone-duo), [Platform modes](https://www.appetiteui.com/docs/platform-bridge#platform-modes) | | Dynamic Island | States, system presentations and expanded layouts for Live Activities. | [Dynamic Island on the iOS page](https://www.appetiteui.com/docs/ios#dynamic-island) | | Charts and tables | 16 chart components on a categorical palette with chart tokens, plus Legend and Sparkline. Table with a pinned column and typed cells. | [Chart](https://www.appetiteui.com/docs/chart), [Table](https://www.appetiteui.com/docs/table), [Colors](https://www.appetiteui.com/docs/colors) | | Tasks app | 10 screens in light and dark: My work, Board, Table, Timeline, Task, Project, Inbox, Search, Filters and New task. | [Tasks screens](https://www.appetiteui.com/docs/screens-tasks) | | Time and Color Picker | A time slot list, quick durations, a spectrum and a hue slider in the Date Picker card. | [Picker](https://www.appetiteui.com/docs/picker) | | Liquid Glass | Three effect styles, Clear, Regular and Tinted, the stops of the iOS transparency setting. | [Effects](https://www.appetiteui.com/docs/effects#glass) | | Focus and states | Focused on Button, Checkbox, Radio and Toggle, Error on Checkbox, a ring spinner for every Loading state, and the bg/raised token for sheets and menus in dark. | [Button](https://www.appetiteui.com/docs/button), [Checkbox](https://www.appetiteui.com/docs/checkbox), [Effects](https://www.appetiteui.com/docs/effects#focus), [Colors](https://www.appetiteui.com/docs/colors) | | Apple system dialogs | Passkey, Permission Alert and Review Prompt, plus brand marks in 14 groups. | [iOS](https://www.appetiteui.com/docs/ios), [Assets](https://www.appetiteui.com/docs/assets) | | Company logos | Twelve placeholder companies as a symbol or a lockup, in color or mono. | [Assets](https://www.appetiteui.com/docs/assets) | | Motion and progress | Motion shown as keyframe filmstrips, and Typing Indicator in its own section. | [Motion](https://www.appetiteui.com/docs/motion), [Progress](https://www.appetiteui.com/docs/progress) | | Shape and type | Headings in Inter Display with tracking per size, radius steps of 40 and 48, chips and search as capsules, cards at radius 24. | [Typography](https://www.appetiteui.com/docs/typography), [Dimensions](https://www.appetiteui.com/docs/dimensions), [Chip](https://www.appetiteui.com/docs/chip), [Card](https://www.appetiteui.com/docs/card) | | Components after current apps | Drawer, text input, swipe actions and top bars, Composer in Input, a compact List row, Table Layout and Top Bar size md. | [Input](https://www.appetiteui.com/docs/input), [List](https://www.appetiteui.com/docs/list), [Top bars](https://www.appetiteui.com/docs/top-bars), [Drawer](https://www.appetiteui.com/docs/drawer) | | iOS 27 | Status bar glyphs, Toggle, Slider and Tab Bar follow the iOS 27 kit, and Action Sheet is the glass card. | [iOS](https://www.appetiteui.com/docs/ios), [Toggle](https://www.appetiteui.com/docs/toggle) | The [changelog](https://www.appetiteui.com/changelog) lists what each release added, with dates. ## Where does it fit next to Apple's and Google's kits? Apple's and Google's kits give you each platform's baseline. Appetite UI names their slots and points them at your tokens, so your brand sits on top of the baseline. Platform Bridge holds 113 variables for this: 53 Apple slots and 60 Material 3 slots, in two modes. Switch to System mode and the same slot points back at the platform value, so you can check a screen against the native palette without unpicking anything. [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge) lists every slot. ## How is the token system built? A component never names a color. It names a token, the token names a foundation, and the chain runs one way only. | Collection | What it decides | Variables | | --- | --- | --- | | Foundations | Raw color ramps, and the spacing, radius, border and icon scales | 202 | | Color Tokens | Semantic color in Light and Dark: bg, text, border, fg, state, brand | 190 | | Platform Bridge | Material 3 and Apple slot names, in Brand and System modes | 113 | | Motion | 5 durations, 5 easing curves, 3 springs and the presets built from them | 31 | | Typography | Size, line height, tracking, weight and family | 33 | | Platform | Touch targets, safe areas, bar heights and corners, per platform | 20 | Six collections, 589 variables, one direction of travel. Nothing points back up the chain, which is what lets the structure survive scale. `platform/min-touch-target` reads 44 pt in the iOS modes and 48 dp in android, so one component obeys both without a second copy. ## How do the tokens reach code? One W3C Design Tokens source generates CSS, SwiftUI, Compose and Flutter, so the value your engineer ships is the value you drew. Some values need no translation at all: `motion/easing/standard` holds `cubic-bezier(0.2, 0, 0, 1)` and `motion/duration/base` holds 200. [Code output](https://www.appetiteui.com/docs/code-output) shows the exporter and the generated files. ## What does the kit include? One Figma file with the components, Apple and Material 3 pattern pages, ready app screens, icons and styles, all reading from one set of variables. | Area | What you get | Count | | --- | --- | --- | | Components | Built for touch, every value bound to a token | 38 pages | | Apple patterns | iOS conventions redrawn in Appetite UI geometry | 20 pages | | Material 3 patterns | Material conventions redrawn in Appetite UI geometry | 17 pages | | Application screens | Onboarding, Settings, Empty State, Finance, Fitness, Social, AI, Booking, Foodie, Tasks and iPhone Duo | 11 sets | | Icons | Lucide, one stroke weight variable at 24 and lighter strokes at small sizes | 1,667 | | Styles | 20 text, 16 effect, 5 grid, and deliberately no paint styles | 41 | Inter is licensed under the SIL Open Font License 1.1 and Lucide under the ISC License, both cleared for commercial work. The Apple and Material pattern pages carry no vendor design resource. The Assets page ships third party brand marks, flags and emoji for realistic mock-ups: they belong to their owners, and you replace them before you ship. The Appetite UI logo and the twelve placeholder company logos are ours. --- --- title: Install the library description: Duplicate the Appetite UI file for one project or publish it as a Figma library for a team, then check that the variables and components arrive. group: Get started source: https://www.appetiteui.com/docs/install dateModified: 2026-10-03 --- # Install the library Updated: October 3, 2026. Duplicate the Appetite UI file for one project, or publish it as a Figma library for a team. Either way the variables, styles and components arrive in the Assets panel, and you can bind your first screen to a token. ## What do I need before I start? A paid Figma plan, because variable modes and team libraries both need one. You also need a working knowledge of Auto Layout, components, variants and Variables. Light and dark mode switch through Figma's variable modes. If you are still getting familiar with Figma, these two resources cover the basics: ## How do I install Appetite UI in Figma? Duplicate the file for one project, or publish it as a Figma library for a team. Either way you work from a copy you own, with no plugin, no account and no setup call. | Topic | Duplicate per project | Shared library | | --- | --- | --- | | Best for | A solo designer or a one-off project | A team, or several projects on one system | | You get | A standalone copy you can strip down | One source file that every project pulls from | | Updates | None by themselves, duplicate the new version again | Figma notifies every file that uses the library | ### Option 1: duplicate per project Right-click the Appetite UI file in the Figma file browser and hit Duplicate. You get a standalone copy. Strip out the components you do not need, customize the tokens, and start designing. It is faster for a single app, because there is nothing to publish. ![The Figma file context menu with Duplicate highlighted by the pointer, below Create branch and File color profile. Publish library is the second entry from the top.](https://www.appetiteui.com/images/docs-install-duplicate.png) Right-click the Appetite UI file and hit Duplicate. ### Option 2: use it as a shared library Keep Appetite UI as a single source file and publish it as a Figma library. Every project pulls components from the same place, and updates flow through Figma's notifications. For option 2, consider splitting Appetite UI into smaller, focused libraries: one for components, one for tokens, one for icons. It takes upfront effort, but it gives your team granular control over what gets published and updated. ## How do I publish and use it as a library? Choose Publish library in the file menu, then enable Appetite UI from the Assets panel of any other file. Components, styles and variables all become available there. When you update a component or token in the source file and re-publish, every file using that library gets a notification. Your team decides when to accept it, and nothing changes without explicit action. ## How do I check that it worked? Open the Variables panel and count: six collections and 589 variables. Then open the Assets panel and place a component. Setting your own brand color and type takes about ten minutes, because you edit a handful of primitives and every component follows. ## How do I update from an earlier version? Every future release is included in your license, and each release comes with an email. A duplicate is a standalone copy and does not update itself, so duplicate the new version again. A published library updates through Figma: publish the new version and each file that uses it gets a notification. Accepting an update can change values you have already placed, such as a radius, a glass style or a state. The [changelog](https://www.appetiteui.com/changelog) lists what each release changes, with dates, and [the introduction](https://www.appetiteui.com/docs/introduction#features) names the page that explains each area. If you publish the file as a library, your team decides when to accept the update, and nothing changes in a project file until someone does. ## How do I keep the file small? Delete the pages you will not use. Appetite UI ships with many components, and a lean file publishes faster and is quicker to browse in the Assets panel. Go through the file at the start of each project and delete the pages and components you know you will not use. Right-click any page in the left sidebar and hit “Delete page.” ![The Figma pages list with the right-click menu open on the Alert page and Delete page highlighted below Copy link to page, Rename page and Duplicate page.](https://www.appetiteui.com/images/docs-install-delete-page.png) Right-click a page in the left sidebar and hit Delete page. You can always duplicate again from the original if you need something back. --- --- title: Colors description: Appetite UI color tokens for Figma: ten primitive ramps, 120 semantic roles in light and dark, and the alpha, chart and Liquid Glass tokens. group: Foundations source: https://www.appetiteui.com/docs/colors dateModified: 2026-10-03 --- # Colors Updated: October 3, 2026. Ten primitive ramps feed 120 semantic roles across light and dark. Bind a component to the role and the value follows the mode, the platform and the code. ## How do color tokens work? Primitives hold raw values, semantic roles point at primitives, and components bind to roles. The arrow runs one way, so one edit to a primitive reaches every component that uses it. Foundations are the raw color values that power the entire system. Every token, every component color and every light and dark mapping traces back to a foundation variable. Each hue follows a consistent 50 to 950 scale, giving you 11 shades from near-white to near-black. Gray adds a 0 step and a 150 step, so it carries 13. The naming is predictable: blue-500 is always the midpoint, blue-50 is the lightest tint, blue-950 is the deepest shade. Every hue uses the same logic, so once you learn one, you know them all. Foundations holds 154 colors: 112 ramp steps and 42 alpha steps. Every hex was read from the Figma file on October 2, 2026. ## Gray Gray runs from 0 to 950 with an extra 150 step, and gray-500 is #8E8E93. Neutral shades carry structure. Backgrounds, text, borders, dividers. They stay out of the way so your color decisions land where they matter. Gray runs 0 to 950, and gray-500 is #8E8E93. The primitives are the same in light and dark. | Token | Hex | | --- | --- | | gray-0 | #FFFFFF | | gray-50 | #F4F5F5 | | gray-100 | #E9E9EA | | gray-150 | #DEDEE0 | | gray-200 | #D1D1D6 | | gray-300 | #C7C7CC | | gray-400 | #AEAEB2 | | gray-500 | #8E8E93 | | gray-600 | #636366 | | gray-700 | #48484A | | gray-800 | #2F2F31 | | gray-900 | #242427 | | gray-950 | #0E0E0F | ## Blue Blue runs from 50 to 950, and blue-500 is #155DFC. Trust, reliability, focus. Blue is a safe default for primary actions in digital products. It reads well across cultures and carries minimal emotional baggage. Blue runs 50 to 950, and blue-500 is #155DFC. The primitives are the same in light and dark. | Token | Hex | | --- | --- | | blue-50 | #EFF6FF | | blue-100 | #DBEAFE | | blue-200 | #BEDBFF | | blue-300 | #82BFFF | | blue-400 | #2B7FFF | | blue-500 | #155DFC | | blue-600 | #1447E6 | | blue-700 | #193CB8 | | blue-800 | #1C398E | | blue-900 | #0D2673 | | blue-950 | #132150 | ## Red Red runs from 50 to 950, and red-500 is #FB2C36. Urgency and attention. Red triggers an immediate response. Use it sparingly and intentionally. In UI, it works best when reserved for moments that genuinely need the user to stop and pay attention. Red runs 50 to 950, and red-500 is #FB2C36. The primitives are the same in light and dark. | Token | Hex | | --- | --- | | red-50 | #FEF2F2 | | red-100 | #FFE2E2 | | red-200 | #FFC9C9 | | red-300 | #FFA2A2 | | red-400 | #FF6467 | | red-500 | #FB2C36 | | red-600 | #E7000B | | red-700 | #C10007 | | red-800 | #9F0712 | | red-900 | #82181A | | red-950 | #460809 | ## Orange Orange runs from 50 to 950, and orange-500 is #FF6900. Energy without alarm. Orange sits between red's urgency and yellow's warmth: it draws attention without triggering anxiety. A strong choice for caution signals or bold secondary accents. Orange runs 50 to 950, and orange-500 is #FF6900. The primitives are the same in light and dark. | Token | Hex | | --- | --- | | orange-50 | #FFF7ED | | orange-100 | #FFEDD4 | | orange-200 | #FFD6A7 | | orange-300 | #FFB86A | | orange-400 | #FF8904 | | orange-500 | #FF6900 | | orange-600 | #F54900 | | orange-700 | #CA3500 | | orange-800 | #9F2D00 | | orange-900 | #7E2A0C | | orange-950 | #441306 | ## Yellow Yellow runs from 50 to 950, and yellow-500 is #FE9A00. Optimism, warmth, visibility. Yellow carries high luminance, which makes it useful for highlights and attention markers. Handle it with care on light backgrounds: contrast can drop quickly. Yellow runs 50 to 950, and yellow-500 is #FE9A00. The primitives are the same in light and dark. | Token | Hex | | --- | --- | | yellow-50 | #FFFBEB | | yellow-100 | #FEF3C6 | | yellow-200 | #FEE685 | | yellow-300 | #FFD230 | | yellow-400 | #FFB900 | | yellow-500 | #FE9A00 | | yellow-600 | #E17100 | | yellow-700 | #BB4D00 | | yellow-800 | #973C00 | | yellow-900 | #7B3306 | | yellow-950 | #461901 | ## Green Green runs from 50 to 950, and green-500 is #22C55E. Progress, safety, confirmation. Green signals "go" in most interfaces: it reassures users that things are working as expected. The natural pick for positive feedback and completed states. Green runs 50 to 950, and green-500 is #22C55E. The primitives are the same in light and dark. | Token | Hex | | --- | --- | | green-50 | #F0FDF4 | | green-100 | #DCFCE7 | | green-200 | #BBF7D0 | | green-300 | #86EFAC | | green-400 | #4ADE80 | | green-500 | #22C55E | | green-600 | #16A34A | | green-700 | #15803D | | green-800 | #166534 | | green-900 | #14532D | | green-950 | #09361B | ## Purple Purple runs from 50 to 950, and purple-500 is #7D52F4. Creativity, premium, distinction. Purple stands apart from the typical blue-green UI palette, making it effective for feature highlights, premium tiers, or brands that want to feel different without being loud. Purple runs 50 to 950, and purple-500 is #7D52F4. The primitives are the same in light and dark. | Token | Hex | | --- | --- | | purple-50 | #EFEBFF | | purple-100 | #DCD5FF | | purple-200 | #CAC0FF | | purple-300 | #A897FF | | purple-400 | #8C71F6 | | purple-500 | #7D52F4 | | purple-600 | #693EE0 | | purple-700 | #5B2CC9 | | purple-800 | #4C25A7 | | purple-900 | #3D1D86 | | purple-950 | #351A75 | ## Sky Sky runs from 50 to 950, and sky-500 is #47C2FF. Calm, clarity, openness. A cooler, softer alternative to primary blue. Sky works well for informational contexts where you want color without weight: tooltips, info banners, secondary surfaces. Sky runs 50 to 950, and sky-500 is #47C2FF. The primitives are the same in light and dark. | Token | Hex | | --- | --- | | sky-50 | #EBF8FF | | sky-100 | #D5F1FF | | sky-200 | #C0EAFF | | sky-300 | #97DCFF | | sky-400 | #68CDFF | | sky-500 | #47C2FF | | sky-600 | #35ADE9 | | sky-700 | #2597D0 | | sky-800 | #1F7EAD | | sky-900 | #18658B | | sky-950 | #124B68 | ## Pink Pink runs from 50 to 950, and pink-500 is #FB4BA3. Playfulness, warmth, approachability. Pink softens digital interfaces without losing energy. It works for lifestyle products, social features, or anywhere your brand leans expressive. Bolder shades carry confidence. Lighter tints feel inviting. Pink runs 50 to 950, and pink-500 is #FB4BA3. The primitives are the same in light and dark. | Token | Hex | | --- | --- | | pink-50 | #FFEBF4 | | pink-100 | #FFD5EA | | pink-200 | #FFC0DF | | pink-300 | #FF97CB | | pink-400 | #FF68B3 | | pink-500 | #FB4BA3 | | pink-600 | #E9358F | | pink-700 | #D0257A | | pink-800 | #AD1F66 | | pink-900 | #8B1852 | | pink-950 | #68123D | ## Teal Teal runs from 50 to 950, and teal-500 is #22D3BB. Balance, sophistication, modernity. Teal bridges blue's trust with green's calm. A strong choice for products in health, finance, or sustainability, or anywhere you need a cool accent that isn't blue. Teal runs 50 to 950, and teal-500 is #22D3BB. The primitives are the same in light and dark. | Token | Hex | | --- | --- | | teal-50 | #E4FBF8 | | teal-100 | #D0FBF5 | | teal-200 | #C2F5EE | | teal-300 | #84EBDD | | teal-400 | #3FDEC9 | | teal-500 | #22D3BB | | teal-600 | #1DAF9C | | teal-700 | #178C7D | | teal-800 | #1A7569 | | teal-900 | #16645A | | teal-950 | #0B463E | ## Where does alpha live? In the token, never in the paint. Figma re-derives a paint's opacity from the bound variable when a component is instanced, so a paint set to 20 percent over an opaque token renders solid. Every hue also includes three alpha (transparent) variants at 10%, 16%, and 24% opacity. Use these for overlays, hover states, pressed states, and subtle tinted backgrounds where you need a color to blend with whatever sits underneath. | Alpha set | Base | Opacities | | --- | --- | --- | | White | #FFFFFF | 10%, 16%, 24%, 72%, 88%, 92% | | Black | #030712 | 10%, 16%, 24% | | Gray | #6A7282 | 10%, 16%, 24% | | Gray 900 | #242426 | 55%, 72%, 88% | | Blue | #2B7FFF | 10%, 16%, 24% | | Red | #FB2C36 | 10%, 16%, 24% | | Orange | #FF6900 | 10%, 16%, 24% | | Yellow | #FE9A00 | 10%, 16%, 24% | | Green | #22C55E | 10%, 16%, 24% | | Purple | #7D52F4 | 10%, 16%, 24% | | Sky | #47C2FF | 10%, 16%, 24% | | Pink | #FB4BA3 | 10%, 16%, 24% | | Teal | #22D3BB | 10%, 16%, 24% | Each tile is painted over a split ground, white on the left and static-black-950 on the right, so a translucent value reads translucent against both. Beside the nine hues, the file carries 13 alpha sets in all: black and gray at 10, 16 and 24 percent, white also at 72, 88 and 92, and gray-900 at 55, 72 and 88. They back the glass layers and the tinted status fills. Static alpha tokens cover the values a design needs without a hue: static-white-alpha at 20, 25, 40, 45, 60 and 70, and static-black-alpha at 20, 40 and 60. brand/alpha-48 and brand/alpha-72 are the two strongest steps of the Heatmap ramp. ## Which role should I bind a layer to? Bind to the role that names its job. A role says what a color is for, so the decision gets made once and every component inherits it. Each swatch is cut on the diagonal, Light above the cut and Dark below it, and where a role holds the same value in both modes the cut disappears. ### Backgrounds bg/raised is the surface of anything that floats above the page: sheets, dialogs, menus, pickers and toasts. In Light it matches bg/white-0. In Dark it lifts to #242427 so the surface separates from the page. bg/glass and bg/glass-thick carry the alpha in the token, because a glass effect over an opaque fill renders flat. | Token | Light | Dark | | --- | --- | --- | | bg/white-0 | #FFFFFF | #0E0E0F | | bg/weak-50 | #F4F5F5 | #242427 | | bg/soft-100 | #E9E9EA | #48484A | | bg/sub-200 | #D1D1D6 | #636366 | | bg/sub-300 | #C7C7CC | #8E8E93 | | bg/surface-800 | #2F2F31 | #D1D1D6 | | bg/surface-top | #DEDEE0 | #48484A | | bg/strong-950 | #0E0E0F | #FFFFFF | | bg/raised | #FFFFFF | #242427 | | bg/elevated | #FFFFFF | #48484A | | bg/elevated-1 | #E9E9EA | #2F2F31 | | bg/elevated-2 | #D1D1D6 | #48484A | | bg/grouped-canvas | #F4F5F5 | #0E0E0F | | bg/grouped-cell | #FFFFFF | #242427 | | bg/glass | #FFFFFF at 72% | #242426 at 55% | | bg/glass-thick | #FFFFFF at 92% | #242426 at 88% | | bg/scrim | #000000 at 40% | #000000 at 48% | ### Text | Token | Light | Dark | | --- | --- | --- | | text/strong-950 | #0E0E0F | #FFFFFF | | text/sub-700 | #48484A | #C7C7CC | | text/soft-500 | #8E8E93 | #AEAEB2 | | text/disabled-400 | #AEAEB2 | #8E8E93 | | text/white-0 | #FFFFFF | #0E0E0F | | text/on-color/strong | #FFFFFF | #FFFFFF | | text/on-color/subtle | #FFFFFF at 88% | #FFFFFF at 88% | ### Foreground, icons | Token | Light | Dark | | --- | --- | --- | | fg/strong-950 | #0E0E0F | #FFFFFF | | fg/sub-700 | #48484A | #C7C7CC | | fg/soft-500 | #8E8E93 | #AEAEB2 | | fg/disabled-400 | #AEAEB2 | #8E8E93 | | fg/white-0 | #FFFFFF | #0E0E0F | | icon/on-color | #FFFFFF | #FFFFFF | ### Borders | Token | Light | Dark | | --- | --- | --- | | border/soft-100 | #E9E9EA | #2F2F31 | | border/sub-200 | #D1D1D6 | #48484A | | border/strong-950 | #0E0E0F | #FFFFFF | | border/white-0 | #FFFFFF | #0E0E0F | ### Brand brand/alpha-10, 16 and 24 tint a surface. brand/alpha-48 and brand/alpha-72 are the two strongest steps of the Heatmap intensity ramp in the Chart components. | Token | Light | Dark | | --- | --- | --- | | brand/base | #155DFC | #2B7FFF | | brand/dark | #193CB8 | #82BFFF | | brand/darker | #1C398E | #BEDBFF | | brand/light | #DBEAFE | #0D2673 | | brand/lighter | #EFF6FF | #132150 | | brand/alpha-10 | #2B7FFF at 10% | #2B7FFF at 10% | | brand/alpha-16 | #2B7FFF at 16% | #2B7FFF at 16% | | brand/alpha-24 | #2B7FFF at 24% | #2B7FFF at 24% | | brand/alpha-48 | #2B7FFF at 48% | #2B7FFF at 48% | | brand/alpha-72 | #2B7FFF at 72% | #2B7FFF at 72% | | brand/pressed | #193CB8 | #155DFC | ### State, base steps | Token | Light | Dark | | --- | --- | --- | | state/error/base-500 | #FB2C36 | #FB2C36 | | state/error/dark-700 | #C10007 | #FFA2A2 | | state/warning/base-500 | #FF6900 | #F54900 | | state/success/base-500 | #22C55E | #16A34A | | state/information/base-500 | #155DFC | #155DFC | | state/away/base-500 | #FE9A00 | #E17100 | | state/feature/base-500 | #7D52F4 | #693EE0 | | state/highlighted/base-500 | #FB4BA3 | #E9358F | | state/stable/base-500 | #22D3BB | #1DAF9C | | state/verified/base-500 | #47C2FF | #35ADE9 | | state/faded/base-500 | #8E8E93 | #636366 | ### State, tint and dark steps Every status family has the same four steps. lighter-50 is a quiet fill, light-200 a stronger tint, base-500 the signal and dark-950 the text that sits on a tint. In Dark, lighter-50 and light-200 point at an alpha of 16 and 24 percent, so a tint stays translucent. state/pressed/on-strong is the press layer for a control on a strong surface. | Token | Light | Dark | | --- | --- | --- | | state/error/lighter-50 | #FEF2F2 | #FB2C36 at 16% | | state/error/light-200 | #FFC9C9 | #FB2C36 at 24% | | state/error/dark-950 | #460809 | #FFA2A2 | | state/warning/lighter-50 | #FFF7ED | #FF6900 at 16% | | state/warning/light-200 | #FFD6A7 | #FF6900 at 24% | | state/warning/dark-950 | #441306 | #FFB86A | | state/success/lighter-50 | #F0FDF4 | #22C55E at 16% | | state/success/light-200 | #BBF7D0 | #22C55E at 24% | | state/success/dark-950 | #09361B | #86EFAC | | state/information/lighter-50 | #EFF6FF | #2B7FFF at 16% | | state/information/light-200 | #BEDBFF | #2B7FFF at 24% | | state/information/dark-950 | #132150 | #82BFFF | | state/away/lighter-50 | #FFFBEB | #FE9A00 at 16% | | state/away/light-200 | #FEE685 | #FE9A00 at 24% | | state/away/dark-950 | #461901 | #FFD230 | | state/feature/lighter-50 | #EFEBFF | #7D52F4 at 16% | | state/feature/light-200 | #CAC0FF | #7D52F4 at 24% | | state/feature/dark-950 | #351A75 | #A897FF | | state/highlighted/lighter-50 | #FFEBF4 | #FB4BA3 at 16% | | state/highlighted/light-200 | #FFC0DF | #FB4BA3 at 24% | | state/highlighted/dark-950 | #68123D | #FF97CB | | state/stable/lighter-50 | #E4FBF8 | #22D3BB at 16% | | state/stable/light-200 | #C2F5EE | #22D3BB at 24% | | state/stable/dark-950 | #0B463E | #84EBDD | | state/verified/lighter-50 | #EBF8FF | #47C2FF at 16% | | state/verified/light-200 | #C0EAFF | #47C2FF at 24% | | state/verified/dark-950 | #124B68 | #97DCFF | | state/faded/lighter-50 | #F4F5F5 | #6A7282 at 16% | | state/faded/light-200 | #D1D1D6 | #6A7282 at 24% | | state/faded/dark-950 | #0E0E0F | #C7C7CC | | state/pressed/on-strong | #FFFFFF at 10% | #030712 at 10% | ### Static, never switch Alpha lives in the token, never in the paint. Figma re-derives paint opacity from the bound variable when a component is instanced, so a paint set to 20 percent over an opaque token renders solid. The two Facebook blues are for the Social Button and are the same in both modes. | Token | Light | Dark | | --- | --- | --- | | static/static-white-0 | #FFFFFF | #FFFFFF | | static/static-black-950 | #0E0E0F | #0E0E0F | | static/static-black-1000 | #000000 | #000000 | | static/static-white-alpha-20 | #FFFFFF at 20% | #FFFFFF at 20% | | static/static-white-alpha-25 | #FFFFFF at 25% | #FFFFFF at 25% | | static/static-white-alpha-40 | #FFFFFF at 40% | #FFFFFF at 40% | | static/static-white-alpha-45 | #FFFFFF at 45% | #FFFFFF at 45% | | static/static-white-alpha-60 | #FFFFFF at 60% | #FFFFFF at 60% | | static/static-white-alpha-70 | #FFFFFF at 70% | #FFFFFF at 70% | | static/static-black-alpha-20 | #000000 at 20% | #000000 at 20% | | static/static-black-alpha-40 | #000000 at 40% | #000000 at 40% | | static/static-black-alpha-60 | #000000 at 60% | #000000 at 60% | | static/static-facebook-blue | #1877F2 | #1877F2 | | static/static-facebook-blue-pressed | #106BE1 | #106BE1 | ### Chart chart/series-1 to 4 are the four series: brand blue, purple, teal and amber. Past four categories, group the rest into chart/muted. chart/soft draws de-emphasized data, such as inactive bars and the series you compare against. | Token | Light | Dark | | --- | --- | --- | | chart/series-1 | #155DFC | #2B7FFF | | chart/series-2 | #7D52F4 | #693EE0 | | chart/series-3 | #22D3BB | #1DAF9C | | chart/series-4 | #FE9A00 | #E17100 | | chart/muted | #D1D1D6 | #6A7282 at 24% | | chart/soft | #DEDEE0 | #6A7282 at 24% | ### Glass The colors behind Liquid Glass. The glass/* tokens are used inside the Liquid Glass effect styles and by controls that sit on glass. glass/edge and glass/rim hold Apple measured values. glass/tint-clear, glass/tint-regular and glass/tint-tinted are the three tint levels. | Token | Light | Dark | | --- | --- | --- | | glass/fill | #030712 at 10% | #FFFFFF at 16% | | glass/fill-strong | #030712 at 24% | #FFFFFF at 24% | | glass/separator | #030712 at 10% | #FFFFFF at 10% | | glass/border | #FFFFFF at 50% | #FFFFFF at 12% | | glass/edge | #DBDBDB | #A6A6A6 | | glass/edge-shade | #000000 at 8% | #000000 at 50% | | glass/rim | #282828 | #1A1A1A | | glass/rim-light | #FFFFFF at 75% | #FFFFFF at 28% | | glass/shadow | #000000 at 25% | #000000 at 45% | | glass/lift | #000000 at 4% | #000000 at 24% | | glass/tint-clear | #FFFFFF at 6% | #FFFFFF at 8% | | glass/tint-regular | #FFFFFF at 32% | #4D4D52 at 45% | | glass/tint-tinted | #F7F7FA at 86% | #38383D at 86% | Chart holds the four series colors and two neutrals for de-emphasized data. bg/raised is the surface of sheets, dialogs, menus, pickers and toasts, and in Dark it lifts to #242427. Glass is the family behind Liquid Glass in its Clear, Regular and Tinted levels, with bg/glass-thick for surfaces that carry content. state/pressed/on-strong is the press layer on a strong surface. Of the 190 Color Tokens variables, 120 are Appetite UI roles, grouped here the way the Figma collection is grouped. The rest are left out: mode/name, annotation/*, which is a redline layer for Figma documentation boards, and the 67 platform/ios and platform/m3 mirrors, which belong to the Platform Bridge, iOS and Material 3 pages. The Color Tokens collection holds 190 variables, read from the Figma file on October 2, 2026. ## How does dark mode work in the token system? In Dark a role changes which primitive it points at, and keeps its name. text/strong-950 points at gray/950 in Light and at gray/0 in Dark, so the token inverts on its own and no component needs a dark variant. Color Tokens carries two modes, Light and Dark. Foundations carries one. One asymmetry is worth knowing. In Light the light-200 and lighter-50 steps of a status family alias solid ramp steps, 200 and 50. In Dark they alias alpha-24 and alpha-16 of the same hue. A tinted surface therefore stays translucent on a dark ground, and a soft error banner reads as a tint in Dark. Tinted status steps and what each mode resolves them to. | Token | Light | Light resolves to | Dark | Dark resolves to | | --- | --- | --- | --- | --- | | state/error/light-200 | #FFC9C9 | red/200 | #FB2C36 at 24% | red alpha 24 | | state/error/lighter-50 | #FEF2F2 | red/50 | #FB2C36 at 16% | red alpha 16 | | state/warning/light-200 | #FFD6A7 | orange/200 | #FF6900 at 24% | orange alpha 24 | | state/warning/lighter-50 | #FFF7ED | orange/50 | #FF6900 at 16% | orange alpha 16 | | state/success/light-200 | #BBF7D0 | green/200 | #22C55E at 24% | green alpha 24 | | state/success/lighter-50 | #F0FDF4 | green/50 | #22C55E at 16% | green alpha 16 | | state/information/light-200 | #BEDBFF | blue/200 | #2B7FFF at 24% | blue alpha 24 | | state/information/lighter-50 | #EFF6FF | blue/50 | #2B7FFF at 16% | blue alpha 16 | The same pattern runs through away, feature, highlighted, stable, verified and faded. The Tokens section below lists all ten families. ## Tokens The Appetite UI semantic set, resolved. The small line under each hex names what the value lands on: a Foundations step, an alpha of one, direct where the role holds a raw hex and a ramp edit will not reach it, or fixed value where the role must never switch. Copy the token name. The hex is there for reference. ### Backgrounds, resolved Backgrounds roles and what each value resolves to. | Token | Light | Light resolves to | Dark | Dark resolves to | | --- | --- | --- | --- | --- | | bg/white-0 | #FFFFFF | gray/0 | #0E0E0F | gray/950 | | bg/weak-50 | #F4F5F5 | gray/50 | #242427 | gray/900 | | bg/soft-100 | #E9E9EA | gray/100 | #48484A | gray/700 | | bg/sub-200 | #D1D1D6 | gray/200 | #636366 | gray/600 | | bg/sub-300 | #C7C7CC | gray/300 | #8E8E93 | gray/500 | | bg/surface-800 | #2F2F31 | gray/800 | #D1D1D6 | gray/200 | | bg/surface-top | #DEDEE0 | gray/150 | #48484A | gray/700 | | bg/strong-950 | #0E0E0F | gray/950 | #FFFFFF | gray/0 | | bg/raised | #FFFFFF | gray/0 | #242427 | gray/900 | | bg/elevated | #FFFFFF | direct | #48484A | direct | | bg/elevated-1 | #E9E9EA | gray/100 | #2F2F31 | gray/800 | | bg/elevated-2 | #D1D1D6 | gray/200 | #48484A | gray/700 | | bg/grouped-canvas | #F4F5F5 | direct | #0E0E0F | direct | | bg/grouped-cell | #FFFFFF | direct | #242427 | direct | | bg/glass | #FFFFFF at 72% | white/alpha-72 | #242426 at 55% | gray-900/alpha-55 | | bg/glass-thick | #FFFFFF at 92% | white/alpha-92 | #242426 at 88% | gray-900/alpha-88 | | bg/scrim | #000000 at 40% | direct | #000000 at 48% | direct | ### Text, resolved Text roles and what each value resolves to. | Token | Light | Light resolves to | Dark | Dark resolves to | | --- | --- | --- | --- | --- | | text/strong-950 | #0E0E0F | gray/950 | #FFFFFF | gray/0 | | text/sub-700 | #48484A | gray/700 | #C7C7CC | gray/300 | | text/soft-500 | #8E8E93 | gray/500 | #AEAEB2 | gray/400 | | text/disabled-400 | #AEAEB2 | gray/400 | #8E8E93 | gray/500 | | text/white-0 | #FFFFFF | gray/0 | #0E0E0F | gray/950 | | text/on-color/strong | #FFFFFF | static-white-0 | #FFFFFF | static-white-0 | | text/on-color/subtle | #FFFFFF at 88% | white/alpha-88 | #FFFFFF at 88% | white/alpha-88 | ### Foreground, icons, resolved Foreground, icons roles and what each value resolves to. | Token | Light | Light resolves to | Dark | Dark resolves to | | --- | --- | --- | --- | --- | | fg/strong-950 | #0E0E0F | gray/950 | #FFFFFF | gray/0 | | fg/sub-700 | #48484A | gray/700 | #C7C7CC | gray/300 | | fg/soft-500 | #8E8E93 | gray/500 | #AEAEB2 | gray/400 | | fg/disabled-400 | #AEAEB2 | gray/400 | #8E8E93 | gray/500 | | fg/white-0 | #FFFFFF | gray/0 | #0E0E0F | gray/950 | | icon/on-color | #FFFFFF | static-white-0 | #FFFFFF | static-white-0 | ### Borders, resolved Borders roles and what each value resolves to. | Token | Light | Light resolves to | Dark | Dark resolves to | | --- | --- | --- | --- | --- | | border/soft-100 | #E9E9EA | gray/100 | #2F2F31 | gray/800 | | border/sub-200 | #D1D1D6 | gray/200 | #48484A | gray/700 | | border/strong-950 | #0E0E0F | gray/950 | #FFFFFF | gray/0 | | border/white-0 | #FFFFFF | gray/0 | #0E0E0F | gray/950 | ### Brand, resolved Brand roles and what each value resolves to. | Token | Light | Light resolves to | Dark | Dark resolves to | | --- | --- | --- | --- | --- | | brand/base | #155DFC | blue/500 | #2B7FFF | blue/400 | | brand/dark | #193CB8 | blue/700 | #82BFFF | blue/300 | | brand/darker | #1C398E | blue/800 | #BEDBFF | blue/200 | | brand/light | #DBEAFE | blue/100 | #0D2673 | blue/900 | | brand/lighter | #EFF6FF | blue/50 | #132150 | blue/950 | | brand/alpha-10 | #2B7FFF at 10% | blue alpha on 2B7FFF | #2B7FFF at 10% | blue alpha on 2B7FFF | | brand/alpha-16 | #2B7FFF at 16% | blue alpha on 2B7FFF | #2B7FFF at 16% | blue alpha on 2B7FFF | | brand/alpha-24 | #2B7FFF at 24% | blue alpha on 2B7FFF | #2B7FFF at 24% | blue alpha on 2B7FFF | | brand/alpha-48 | #2B7FFF at 48% | direct | #2B7FFF at 48% | direct | | brand/alpha-72 | #2B7FFF at 72% | direct | #2B7FFF at 72% | direct | | brand/pressed | #193CB8 | blue/700 | #155DFC | blue/500 | ### State, base steps, resolved State, base steps roles and what each value resolves to. | Token | Light | Light resolves to | Dark | Dark resolves to | | --- | --- | --- | --- | --- | | state/error/base-500 | #FB2C36 | red/500 | #FB2C36 | red/500 | | state/error/dark-700 | #C10007 | red/700 | #FFA2A2 | red/300 | | state/warning/base-500 | #FF6900 | orange/500 | #F54900 | orange/600 | | state/success/base-500 | #22C55E | green/500 | #16A34A | green/600 | | state/information/base-500 | #155DFC | blue/500 | #155DFC | blue/500 | | state/away/base-500 | #FE9A00 | yellow/500 | #E17100 | yellow/600 | | state/feature/base-500 | #7D52F4 | purple/500 | #693EE0 | purple/600 | | state/highlighted/base-500 | #FB4BA3 | pink/500 | #E9358F | pink/600 | | state/stable/base-500 | #22D3BB | teal/500 | #1DAF9C | teal/600 | | state/verified/base-500 | #47C2FF | sky/500 | #35ADE9 | sky/600 | | state/faded/base-500 | #8E8E93 | gray/500 | #636366 | gray/600 | ### State, tint and dark steps, resolved State, tint and dark steps roles and what each value resolves to. | Token | Light | Light resolves to | Dark | Dark resolves to | | --- | --- | --- | --- | --- | | state/error/lighter-50 | #FEF2F2 | red/50 | #FB2C36 at 16% | red/alpha-16 | | state/error/light-200 | #FFC9C9 | red/200 | #FB2C36 at 24% | red/alpha-24 | | state/error/dark-950 | #460809 | red/950 | #FFA2A2 | red/300 | | state/warning/lighter-50 | #FFF7ED | orange/50 | #FF6900 at 16% | orange/alpha-16 | | state/warning/light-200 | #FFD6A7 | orange/200 | #FF6900 at 24% | orange/alpha-24 | | state/warning/dark-950 | #441306 | orange/950 | #FFB86A | orange/300 | | state/success/lighter-50 | #F0FDF4 | green/50 | #22C55E at 16% | green/alpha-16 | | state/success/light-200 | #BBF7D0 | green/200 | #22C55E at 24% | green/alpha-24 | | state/success/dark-950 | #09361B | green/950 | #86EFAC | green/300 | | state/information/lighter-50 | #EFF6FF | blue/50 | #2B7FFF at 16% | blue/alpha-16 | | state/information/light-200 | #BEDBFF | blue/200 | #2B7FFF at 24% | blue/alpha-24 | | state/information/dark-950 | #132150 | blue/950 | #82BFFF | blue/300 | | state/away/lighter-50 | #FFFBEB | yellow/50 | #FE9A00 at 16% | yellow/alpha-16 | | state/away/light-200 | #FEE685 | yellow/200 | #FE9A00 at 24% | yellow/alpha-24 | | state/away/dark-950 | #461901 | yellow/950 | #FFD230 | yellow/300 | | state/feature/lighter-50 | #EFEBFF | purple/50 | #7D52F4 at 16% | purple/alpha-16 | | state/feature/light-200 | #CAC0FF | purple/200 | #7D52F4 at 24% | purple/alpha-24 | | state/feature/dark-950 | #351A75 | purple/950 | #A897FF | purple/300 | | state/highlighted/lighter-50 | #FFEBF4 | pink/50 | #FB4BA3 at 16% | pink/alpha-16 | | state/highlighted/light-200 | #FFC0DF | pink/200 | #FB4BA3 at 24% | pink/alpha-24 | | state/highlighted/dark-950 | #68123D | pink/950 | #FF97CB | pink/300 | | state/stable/lighter-50 | #E4FBF8 | teal/50 | #22D3BB at 16% | teal/alpha-16 | | state/stable/light-200 | #C2F5EE | teal/200 | #22D3BB at 24% | teal/alpha-24 | | state/stable/dark-950 | #0B463E | teal/950 | #84EBDD | teal/300 | | state/verified/lighter-50 | #EBF8FF | sky/50 | #47C2FF at 16% | sky/alpha-16 | | state/verified/light-200 | #C0EAFF | sky/200 | #47C2FF at 24% | sky/alpha-24 | | state/verified/dark-950 | #124B68 | sky/950 | #97DCFF | sky/300 | | state/faded/lighter-50 | #F4F5F5 | gray/50 | #6A7282 at 16% | gray/alpha-16 | | state/faded/light-200 | #D1D1D6 | gray/200 | #6A7282 at 24% | gray/alpha-24 | | state/faded/dark-950 | #0E0E0F | gray/950 | #C7C7CC | gray/300 | | state/pressed/on-strong | #FFFFFF at 10% | white/alpha-10 | #030712 at 10% | black/alpha-10 | ### Static, never switch, resolved Static, never switch roles and what each value resolves to. | Token | Light | Light resolves to | Dark | Dark resolves to | | --- | --- | --- | --- | --- | | static/static-white-0 | #FFFFFF | fixed value | #FFFFFF | fixed value | | static/static-black-950 | #0E0E0F | fixed value | #0E0E0F | fixed value | | static/static-black-1000 | #000000 | fixed value | #000000 | fixed value | | static/static-white-alpha-20 | #FFFFFF at 20% | fixed value | #FFFFFF at 20% | fixed value | | static/static-white-alpha-25 | #FFFFFF at 25% | fixed value | #FFFFFF at 25% | fixed value | | static/static-white-alpha-40 | #FFFFFF at 40% | fixed value | #FFFFFF at 40% | fixed value | | static/static-white-alpha-45 | #FFFFFF at 45% | fixed value | #FFFFFF at 45% | fixed value | | static/static-white-alpha-60 | #FFFFFF at 60% | fixed value | #FFFFFF at 60% | fixed value | | static/static-white-alpha-70 | #FFFFFF at 70% | fixed value | #FFFFFF at 70% | fixed value | | static/static-black-alpha-20 | #000000 at 20% | fixed value | #000000 at 20% | fixed value | | static/static-black-alpha-40 | #000000 at 40% | fixed value | #000000 at 40% | fixed value | | static/static-black-alpha-60 | #000000 at 60% | fixed value | #000000 at 60% | fixed value | | static/static-facebook-blue | #1877F2 | fixed value | #1877F2 | fixed value | | static/static-facebook-blue-pressed | #106BE1 | fixed value | #106BE1 | fixed value | ### Chart, resolved Chart roles and what each value resolves to. | Token | Light | Light resolves to | Dark | Dark resolves to | | --- | --- | --- | --- | --- | | chart/series-1 | #155DFC | brand/base, blue/500 | #2B7FFF | brand/base, blue/400 | | chart/series-2 | #7D52F4 | state/feature/base-500, purple/500 | #693EE0 | state/feature/base-500, purple/600 | | chart/series-3 | #22D3BB | state/stable/base-500, teal/500 | #1DAF9C | state/stable/base-500, teal/600 | | chart/series-4 | #FE9A00 | state/away/base-500, yellow/500 | #E17100 | state/away/base-500, yellow/600 | | chart/muted | #D1D1D6 | state/faded/light-200, gray/200 | #6A7282 at 24% | state/faded/light-200, gray/alpha-24 | | chart/soft | #DEDEE0 | gray/150 | #6A7282 at 24% | gray/alpha-24 | ### Glass, resolved Glass roles and what each value resolves to. | Token | Light | Light resolves to | Dark | Dark resolves to | | --- | --- | --- | --- | --- | | glass/fill | #030712 at 10% | black/alpha-10 | #FFFFFF at 16% | white/alpha-16 | | glass/fill-strong | #030712 at 24% | black/alpha-24 | #FFFFFF at 24% | white/alpha-24 | | glass/separator | #030712 at 10% | black/alpha-10 | #FFFFFF at 10% | white/alpha-10 | | glass/border | #FFFFFF at 50% | direct | #FFFFFF at 12% | direct | | glass/edge | #DBDBDB | direct | #A6A6A6 | direct | | glass/edge-shade | #000000 at 8% | direct | #000000 at 50% | direct | | glass/rim | #282828 | direct | #1A1A1A | direct | | glass/rim-light | #FFFFFF at 75% | direct | #FFFFFF at 28% | direct | | glass/shadow | #000000 at 25% | direct | #000000 at 45% | direct | | glass/lift | #000000 at 4% | direct | #000000 at 24% | direct | | glass/tint-clear | #FFFFFF at 6% | direct | #FFFFFF at 8% | direct | | glass/tint-regular | #FFFFFF at 32% | direct | #4D4D52 at 45% | direct | | glass/tint-tinted | #F7F7FA at 86% | direct | #38383D at 86% | direct | A value carrying a percentage is an alpha role, drawn over the ground it sits on: white in Light, near black in Dark. --- --- title: Typography description: The Appetite UI type scale for Figma: ten sizes in Inter and Inter Display, three weights and tracking per size, mapped to iOS Dynamic Type and Material 3. group: Foundations source: https://www.appetiteui.com/docs/typography dateModified: 2026-10-03 --- # Typography Updated: October 3, 2026. Two families, ten sizes, three weights. Every text style reads its size, line height, weight and tracking from 33 variables, so the whole ramp moves together. ## Which typefaces does the kit use? Inter Display for headlines from 6xl to 2xl and Inter for everything from xl to xs. A third variable, System, holds the face for what the operating system draws. Figure: the type ramp, one line per step. Figure: the type ramp, one line per step. Install Inter and Inter Display to see every text style correctly in Figma. Local fonts load in the Figma desktop app only. Inter and Inter Display are both under the SIL Open Font License, so the library stays license clean. To swap a family for the whole system, change the value of typography/fontFamily/Heading or typography/fontFamily/Body. ## What type scale should a mobile app use? Ten sizes from 12 to 60, each with a matched line height. Use xl to xs for interface text and 2xl to 6xl for headlines. Every line below is set in the step it names. Figure: the type scale, every step with its size and line height. Tracking tightens as the size grows. Each display size from 2xl to 6xl has its own value, from -0.24 at 2xl to -1.2 at 6xl, which is -1% to -2% of the size. xl, lg and base sit at 0, and sm and xs open to +0.1. Line height has its own tell: 18 and 20 both set on 28, so lg and xl share one rhythm. Text wrap is part of the style. Balance evens out the lines of xl to 6xl, which are short and often wrap to two lines. Pretty avoids a single word on the last line of xs to lg. ## Which weights does the system use? Three weights, each with one job. default is 400, heading is 500 and emphasized is 600. Each of the ten steps ships twice, as /default and as /emphasized. Figure: the weights the family ships. Use emphasized for labels, buttons and titles up to 2xl. From 3xl up, the /emphasized style takes the heading weight of 500, because a semibold starts to look heavy at headline size. 2xl is where the two meet: its /emphasized style is the one Inter Display style at 600. Limiting the weights keeps hierarchy in size and spacing. Size, line height and tracking are identical across the pair. ## How does the scale map to Dynamic Type and Material roles? Every Apple text style and every Material 3 type role resolves to one of the ten steps, through variables in the Platform Bridge collection. | Step | Apple text style | Material 3 role | | --- | --- | --- | | 6xl 60 | none | displayLarge | | 5xl 48 | none | displayMedium | | 4xl 36 | largeTitle | displaySmall | | 3xl 30 | title1 | headlineLarge, headlineMedium | | 2xl 24 | none | headlineSmall | | xl 20 | title2, title3 | titleLarge | | lg 18 | headline, body | none | | base 16 | callout | titleMedium, bodyLarge | | sm 14 | subheadline | titleSmall, bodyMedium, labelLarge | | xs 12 | footnote, caption1, caption2, tabBarLabel | bodySmall, labelMedium, labelSmall | That table is Brand mode. The same variables have a System mode that returns the platform's own published numbers instead, such as Apple's 17 pt body and Material's 57 sp displayLarge, so a mirror screen can switch platform without being rebuilt. Set the mode on the frame and everything inside follows. The bridge carries the size and only the size. Line height, weight and tracking stay on the Appetite UI side, so a step keeps its rhythm whichever platform name you reach it by. Dynamic Type and Material scaling are runtime behavior that no Figma file can model, so read every number here as the default size class. ## Tokens 20 text styles resting on 33 variables. The styles are what you apply to a layer, and the variables are what move when you change your mind. | Style | Family | Size / line | Tracking | Role | | --- | --- | --- | --- | --- | | 6xl | Inter Display | 60 / 64 | -1.2 | Hero numerals and splash headlines. Rare in mobile. | | 5xl | Inter Display | 48 / 52 | -0.96 | Display. Onboarding hero and large balances. | | 4xl | Inter Display | 36 / 40 | -0.54 | Display small. Screen hero titles. | | 3xl | Inter Display | 30 / 36 | -0.45 | Headline large. Section heroes. | | 2xl | Inter Display | 24 / 32 | -0.24 | Headline. Screen titles and modal headers. | | xl | Inter | 20 / 28 | 0 | Title large. Card titles and sheet headers. | | lg | Inter | 18 / 28 | 0 | Title. List section headers and emphasized body. | | base | Inter | 16 / 24 | 0 | Body. The default reading size. | | sm | Inter | 14 / 20 | 0.1 | Body small. Secondary text and list subtitles. | | xs | Inter | 12 / 16 | 0.1 | Caption and label. Badges, timestamps, tab labels. | Each row is two styles. x/default is Regular 400 and x/emphasized is Medium 500 from 3xl up and Semi Bold 600 from 2xl down. base is the only style with paragraph spacing, 16, because it is the only one that regularly runs past a line. | Variable | Value | Reaches | | --- | --- | --- | | `typography/fontFamily/Heading` | Inter Display | The styles 6xl to 2xl | | `typography/fontFamily/Body` | Inter | The styles xl to xs | | `typography/fontFamily/System` | Inter | Operating system surfaces inside the mirrors. No text style reaches it | | `typography/fontWeight/default` | 400 | The ten /default styles | | `typography/fontWeight/heading` | 500 | The /emphasized styles of 6xl, 5xl, 4xl and 3xl | | `typography/fontWeight/emphasized` | 600 | The /emphasized styles of 2xl to xs | | `typography/letterSpacing/6xl` | -1.2 | 6xl, -2% of the size | | `typography/letterSpacing/5xl` | -0.96 | 5xl, -2% of the size | | `typography/letterSpacing/4xl` | -0.54 | 4xl, -1.5% of the size | | `typography/letterSpacing/3xl` | -0.45 | 3xl, -1.5% of the size | | `typography/letterSpacing/2xl` | -0.24 | 2xl, -1% of the size | | `typography/letterSpacing/normal` | 0 | xl, lg and base | | `typography/letterSpacing/wide` | 0.1 | sm and xs | | `typography/fontSize/xs to 6xl` | 12, 14, 16, 18, 20, 24, 30, 36, 48, 60 | One per step | | `typography/lineHeight/xs to 6xl` | 16, 20, 24, 28, 28, 32, 36, 40, 52, 64 | One per step. The lg styles bind lineHeight/xl, which is also 28 | Both family variables hold the family name as plain text, so changing one moves every style bound to it in Figma and in generated code. Read from the Typography collection and the text styles of the Figma file on October 2, 2026. --- --- title: Icons description: 1,667 Lucide icons in Figma for iOS and Android apps: five sizes, a stroke of 2 at 24 that thins at small sizes, and colors from foreground tokens. group: Foundations source: https://www.appetiteui.com/docs/icons dateModified: 2026-10-03 --- # Icons Updated: October 3, 2026. 1,667 Lucide icons on one 24 box and one stroke variable, in five sizes from 16 to 96. The stroke steps with the size, 1.5 at 16, 2 at 24 and 2.25 at 32, so an icon at 16 and an icon at 32 still belong to the same set. ## Which icons does the file include? 1,667 icons on one box, one pair of end caps and one stroke variable. The set is Lucide, a third party open source library under the ISC license, wired to the tokens. Specimen: 32 of 1,667, drawn at 24. 24 box, stroke 2, round cap, round join. The set is flat, with no variant sets, filed under categories on the overview board and named in Lucide's own kebab case: house, chevron-right, message-circle. The layer name is the search term. ## Which icon size should I use? Use 16 inline with small text, 20 beside a label or in dense rows and compact controls, and 24 as the default. Use 32 for empty states and feature tiles, and 96 for display marks that sit beside a logo, never inside a control. Specimen: One icon at every step, on a common baseline. 16, 20, 24, 32, 96. Size is set by the component that holds the icon, not bound on the icon itself. Button sets 16, 18 or 20 beside a label and 20, 22 or 24 when the button has no label, for its sizes sm, md and lg, so 18 and 22 sit between the token steps. ## How thick is the stroke? Every icon is drawn on a 24 box with a stroke of 2, bound to dimensions/icon/stroke, and an instance at 22 or 24 keeps a stroke of 2. Smaller instances carry a lighter stroke and the 32 step a heavier one, so the line steps with the size. Specimen: The same icon at 16, 20, 24, 32. Read the second line under each glyph. Above, stroke 2 at every size. Below, the stroke the components give the instance. | Icon size | Stroke on most instances | | --- | --- | | 16 | 1.5 | | 18 | 1.75 | | 20 | 1.75 | | 22 | 2 | | 24 | 2 | | 32 | 2.25 | The values below 22 and at 32 are overrides on the instance, not bound to the variable. Changing `dimensions/icon/stroke` moves the masters and the bound instances at 24 and leaves the others where they are. A few instances carry another value, so read the stroke off the instance you copy. All 1,667 masters but circle-check bind strokeWeight to the variable, counted in the Figma file on October 3, 2026. ## Which color does an icon take? An icon has no color of its own. It takes the foreground role of the text beside it, so a label and its icon never drift apart. Specimen: One icon, six foreground roles. The stroke is a variable in every case, never a literal. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `fg/strong-950` | #0E0E0F | #FFFFFF | The default in the library | | `fg/sub-700` | #48484A | #C7C7CC | Neutral outline controls | | `fg/disabled-400` | #AEAEB2 | #8E8E93 | Disabled states | | `brand/base` | #155DFC | #2B7FFF | Brand outline controls | | `state/error/base-500` | #FB2C36 | #FB2C36 | Destructive actions | On a filled Brand or Error button the icon takes `static/static-white-0`, #FFFFFF in both modes. On a filled Neutral button it takes `fg/white-0`, #FFFFFF in Light and #0E0E0F in Dark. Icons are graphics, so WCAG asks 3 to 1 against the ground. On white, strong, sub, brand and error clear it at 19.3, 9.1, 5.2 and 3.8 to 1. The disabled role measures 2.2 to 1, which suits a state that WCAG exempts. In Dark every role in the table is above 5 to 1. All five were read off icon instances inside Button, on October 2, 2026. ## How do I swap an icon without detaching it? Select the instance and pick another icon in Figma's instance swap menu. Every icon is a component with a built-in safe area, so the new glyph lands in the same 24 box and the layout does not shift. The icons are strokes without a fill, so recolor one by changing its stroke color to a foreground token from the table above. Painting the fill floods the area inside the path. In the app, an icon beside a text label is decorative. An icon-only control needs an accessible name for VoiceOver and TalkBack. The touch target stays 44 pt on iOS and 48 dp on Android (`platform/min-touch-target`) whatever the icon size. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Lucide, one outline style, stroke 2 at 24 | SF Symbols, which have a weight axis | Material Symbols, which have a wght axis | One outline set serves both platforms. The Apple and Material pages of the file draw their chrome glyphs from the platform's own vectors, not from Lucide. | ## Tokens Six numbers cover the whole set. Five sizes and one stroke, all in the Foundations collection, one mode. | Token | Value | Used for | | --- | --- | --- | | `dimensions/icon/size/sm` | 16 | Inline with small text, dense rows | | `dimensions/icon/size/md` | 20 | An icon beside a label, compact controls | | `dimensions/icon/size/base` | 24 | The default, and the frame itself | | `dimensions/icon/size/lg` | 32 | Empty states and feature tiles | | `dimensions/icon/size/display` | 96 | Display only, never inside a control | | `dimensions/icon/stroke` | 2 | strokeWeight on the icon masters | Sizes are scoped to width and height, the stroke to stroke weight, so each offers itself only where it belongs. Only the stroke is bound on the icon: size comes from the component holding the instance. --- --- title: Dimensions description: Appetite UI dimension tokens for Figma: a 4 pt spacing scale, eleven radii, four border weights, five icon sizes and the 44 pt and 48 dp touch targets. group: Foundations source: https://www.appetiteui.com/docs/dimensions dateModified: 2026-10-03 --- # Dimensions Updated: October 3, 2026. Spacing, radius, border weight and icon size are four scales of Figma variables, 45 in all. Pick a step and bind it to the layer. ## Preview A corner inside a corner, drawn from the radius tokens. The inner radius is the outer radius minus the padding, so the two curves stay parallel. Four pairs of nested corners: the outer radius token, the padding and the inner radius. | Token | Value | Outer radius | Inset | Inner radius | | --- | --- | --- | --- | --- | | radius/5xl around radius/2xl | 48 outside, 24 padding, 24 inside | 48 | 24 | 24 | | radius/3xl around radius/2xl | 32 outside, 8 padding, 24 inside | 32 | 8 | 24 | | radius/2xl around radius/xl | 24 outside, 8 padding, 16 inside | 24 | 8 | 16 | | radius/lg around radius/md | 12 outside, 4 padding, 8 inside | 12 | 4 | 8 | ## What spacing scale does Appetite UI use? A 4 pt scale in 24 steps, from spacing/0 to spacing/40 at 160. The step number is the value divided by four, so spacing/4 is 16 and spacing/12 is 48. Half steps fill the gaps below 12, such as spacing/1-5 at 6 and spacing/2-5 at 10. Above spacing/12 the scale widens to 14, 16, 20, 24, 30, 32 and 40, because you rarely need 52 when 48 and 56 exist. Bind spacing to gaps and padding in Auto Layout instead of typing a value. The spacing scale, token name, value and a bar drawn at that width. | Token | Value | | --- | --- | | spacing/0 | 0 | | spacing/px | 1 | | spacing/0-5 | 2 | | spacing/1 | 4 | | spacing/1-5 | 6 | | spacing/2 | 8 | | spacing/2-5 | 10 | | spacing/3 | 12 | | spacing/4 | 16 | | spacing/5 | 20 | | spacing/6 | 24 | | spacing/7 | 28 | | spacing/8 | 32 | | spacing/9 | 36 | | spacing/10 | 40 | | spacing/11 | 44 | | spacing/12 | 48 | | spacing/14 | 56 | | spacing/16 | 64 | | spacing/20 | 80 | | spacing/24 | 96 | | spacing/30 | 120 | | spacing/32 | 128 | | spacing/40 | 160 | spacing/30 at 120 clears the content under a floating bar, so the last row stays visible. The default table column reads it. ## Which radius goes inside a rounded container? Subtract the padding from the outer radius. A 24 card with 8 padding holds a 16 image, and a 12 card with 4 padding holds an 8 control. The scale has eleven steps, and each one is a shape decision. radius/full stores 9999 instead of 50 percent, so a tall box keeps semicircular ends and never becomes an ellipse. The radius scale, token name, value and the corner it draws. | Token | Value | | --- | --- | | radius/none | 0 | | radius/sm | 2 | | radius/base | 4 | | radius/md | 8 | | radius/lg | 12 | | radius/xl | 16 | | radius/2xl | 24 | | radius/3xl | 32 | | radius/4xl | 40 | | radius/5xl | 48 | | radius/full | 9999 | radius/xl at 16 is the inner radius of a 24 card at 8 padding, and the Material large shape role maps to it. radius/4xl at 40 is for sheets, modals and full width surfaces, and radius/5xl at 48 holds 24 radius cards at 24 padding. ## Which border weight should I use? Four stroke widths: a 0.75 hairline, a 1 default, a 2 for focus and selection, and a 4 for decoration. The border scale, token name, value and a rule drawn at that weight. | Token | Value | | --- | --- | | border/0-75 | 0.75 | | border/1 | 1 | | border/2 | 2 | | border/4 | 4 | border/4 is for decorative rules only. Never use it as the boundary of something a person can tap. ## Which icon sizes and stroke are there? Five sizes and one stroke. dimensions/icon/stroke is 2, and every glyph bound to it changes weight together when you change that one variable. The icon sizes, token name, value and a box drawn at that size. | Token | Value | | --- | --- | | icon/size/sm | 16 | | icon/size/md | 20 | | icon/size/base | 24 | | icon/size/lg | 32 | | icon/size/display | 96 | The library holds 1,667 Lucide icons drawn on the 24 box, the default size. SF Symbols and Material Symbols both express weight as an axis, which is why stroke is a variable. In the Button set only the icons at 24 bind to dimensions/icon/stroke, so changing the variable moves them and leaves the rest. The icons at 22 carry a stroke of 2, the icons at 18 and 20 a stroke of 1.75 and the icons at 16 a stroke of 1.5, all plain numbers, so a small glyph does not read heavier than the label beside it. ## What is the minimum touch target? 44 pt on iOS and 48 dp on Android. The Platform collection stores both in platform/min-touch-target, so setting the mode on a frame switches the number a control is checked against. A control may draw smaller than its target, as a switch track does, but the frame a finger can hit must not. spacing/11 is the 44 step of the spacing scale. | Variable | iPhone | Android | iPhone Duo | What it sets | | --- | --- | --- | --- | --- | | `platform/min-touch-target` | 44 | 48 | 44 | Smallest tappable square | | `platform/bar/top-height` | 44 | 64 | 44 | Top bar, below the safe area | | `platform/bar/bottom-height` | 49 | 64 | 0 | Bottom bar, a vertical rail on Duo | | `platform/list-row/min-height` | 44 | 56 | 44 | Shortest single line list row | | `platform/screen-padding` | 16 | 16 | 16 | Edge of the screen to content | The Platform collection has 20 variables on five modes. [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge) explains how a mode switches a whole screen. ## Which grid style fits which screen? Five grid styles apply a column count, a gutter, a margin and the two safe areas to a frame in one click. | Style | Screen | Columns | Gutter and margin | Safe area top and bottom | | --- | --- | --- | --- | --- | | `ios-md` | iPhone 16 and 16 Plus | 4 | 16 and 16 | 59 and 34 | | `ios-lg` | iPhone 16 Pro and 16 Pro Max | 4 | 16 and 16 | 62 and 34 | | `android` | Material 3 phone | 4 | 16 and 16 | 52 and 24 | | `ios-duo-outer` | iPhone Duo outer display, 370 pane and 96 rail | 4 | 16 and 16 | 24 and 24 | | `ios-duo-inner` | iPhone Duo inner display, 951 by 669: 855 of content beside the 96 rail. Apply it to the 855 content frame to keep the columns clear of the rail | 6 | 16 and 16 | 24 and 24 | The inner Duo grid has six columns because four columns across the 855 beside the rail would give columns nothing uses. If you design for both platforms, apply the grid of the target device and let Auto Layout handle the rest. The two Duo grids keep the top and bottom safe areas at 24, because the device has no notch to clear. The trailing 96, the room of the rail, comes from grid/safe-area/trailing in the Platform collection. ## Tokens Every value in the collection. 45 variables in one mode across four scales, plus three table column widths that alias the spacing scale. | Token | Value | Used by | | --- | --- | --- | | `dimensions/spacing/0` | 0 | No gap | | `dimensions/spacing/px` | 1 | Hairline | | `dimensions/spacing/0-5` | 2 | Icon to label | | `dimensions/spacing/1` | 4 | Tight gap | | `dimensions/spacing/1-5` | 6 | Chip padding | | `dimensions/spacing/2` | 8 | Label to control | | `dimensions/spacing/2-5` | 10 | Compact row | | `dimensions/spacing/3` | 12 | Field padding | | `dimensions/spacing/4` | 16 | Card padding | | `dimensions/spacing/5` | 20 | Row gap | | `dimensions/spacing/6` | 24 | Card to card | | `dimensions/spacing/7` | 28 | Header padding | | `dimensions/spacing/8` | 32 | Block gap | | `dimensions/spacing/9` | 36 | Wide block gap | | `dimensions/spacing/10` | 40 | Section padding | | `dimensions/spacing/11` | 44 | Tap target | | `dimensions/spacing/12` | 48 | Section gap | | `dimensions/spacing/14` | 56 | Wide section gap | | `dimensions/spacing/16` | 64 | Screen block gap | | `dimensions/spacing/20` | 80 | Screen padding, table action column | | `dimensions/spacing/24` | 96 | Empty state | | `dimensions/spacing/30` | 120 | Scroll clearance under a floating bar, default table column | | `dimensions/spacing/32` | 128 | Hero spacing | | `dimensions/spacing/40` | 160 | Full bleed, table lead column | | `dimensions/radius/none` | 0 | Square corners | | `dimensions/radius/sm` | 2 | Inline marks and tiny chips | | `dimensions/radius/base` | 4 | Small controls and inline fields | | `dimensions/radius/md` | 8 | The Checkbox box, chart bars and tooltips, small icon tiles, and the small corner of the iOS and M3 shape scales | | `dimensions/radius/lg` | 12 | Inner surfaces, list highlights, small cards | | `dimensions/radius/xl` | 16 | Large cards, inner radius of a 24 card at 8 padding | | `dimensions/radius/2xl` | 24 | Cards and grouped containers | | `dimensions/radius/3xl` | 32 | Dialogs and large cards | | `dimensions/radius/4xl` | 40 | Sheets, modals and full width surfaces | | `dimensions/radius/5xl` | 48 | Containers that hold 24 radius cards at 24 padding | | `dimensions/radius/full` | 9999 | Pills, avatars and circles | | `dimensions/icon/size/sm` | 16 | Inline with small text | | `dimensions/icon/size/md` | 20 | Dense list rows and compact controls | | `dimensions/icon/size/base` | 24 | Default size | | `dimensions/icon/size/lg` | 32 | Empty states and feature tiles | | `dimensions/icon/size/display` | 96 | Display marks beside a logo | | `dimensions/icon/stroke` | 2 | Stroke of every bound glyph | | `dimensions/border/0-75` | 0.75 | Hairline | | `dimensions/border/1` | 1 | Inputs, cards and outline buttons | | `dimensions/border/2` | 2 | Focus ring and selected outline | | `dimensions/border/4` | 4 | Decorative rules only | | `table/column/lead` | 160 | Pinned first column of a Table | | `table/column/default` | 120 | Ordinary Table column | | `table/column/action` | 80 | Trailing actions column of a Table | Values and descriptions read from the Foundations collection of the Figma file on October 2, 2026. --- --- title: Effects description: Which effect style goes where in Appetite UI for Figma: six drop shadows, an edge shadow, four blurs, three Liquid Glass styles and two focus rings. group: Foundations source: https://www.appetiteui.com/docs/effects dateModified: 2026-10-03 --- # Effects Updated: October 3, 2026. Appetite UI shows depth with six drop shadows, an edge shadow and four backdrop blurs, puts bars, buttons and sheets on Liquid Glass in three styles, and marks keyboard focus with a 2 pt ring. Pick the style by what the surface is. ## Preview The file holds 16 effect styles in four groups: drop shadows, backdrop blurs, Liquid Glass and focus rings. The shadow ramp comes first, one surface in six steps, because it is the part that reaches the code. Specimen: dropShadow, xs to 2xl. one surface, six steps, black at 1 to 12 percent. Every step is two layers and both are pure black. No step carries a hue or a second value for dark mode. ## Which shadow goes on which surface? Pick the step by what the surface is. Chips and small pressables take xs, cards at rest sm, raised cards and dropdowns md, popovers and menus lg, modals and sheets xl, and full-screen overlays 2xl. Never pick one by how deep it looks. Figure: the elevation levels, each with what it is for. In dark mode a shadow says little. The ramp holds one set of values for both modes, so black at 1 to 12 percent on a #0E0E0F surface barely separates a card from the page. To lift a surface in dark, use the `bg/raised` token (#FFFFFF in Light, #242427 in Dark) instead of a deeper shadow. ## What is the edge shadow for? dropShadow/edge is a side shadow for a pinned column, or for a panel that content scrolls under. It falls to the right of the element that carries it. Specimen: dropShadow/edge. offset 6 and 0, blur 12, spread -4, black at 8 percent. Use it where something stays put while content moves beneath it: the first column of a Table, a sidebar over a scrolling list. A ramp step throws its shadow down, and a pinned edge needs it sideways. It is a single layer, unlike the six steps, and it has no Dark value either. ## Which blur radius should I use? Four backdrop blurs of 8, 16, 24 and 40 pt. A blur needs something behind it, so the element carries a semi-transparent fill. A fully opaque fill leaves nothing for the blur to show through. | Style | Radius | Use | | --- | --- | --- | | `backdropBlur/sm` | 8 | Light scrim blur behind sheets. | | `backdropBlur/md` | 16 | Standard nav bar and tab bar blur. | | `backdropBlur/lg` | 24 | Heavy blur for modal backdrops. | | `backdropBlur/xl` | 40 | Maximum blur for full-screen overlays. | Read the four radii as a sequence. The Tokens table gives blur() as the value to start from on the web, and a Figma blur radius and a CSS blur() radius do not map one to one. ## How do the three Liquid Glass styles differ? They are three stops on the iOS 27 transparency slider. Clear shows the content through the glass, with refraction and a rim light only. Regular is frosted with a defined edge and is the default for bars, buttons, menus and sheets. Tinted is fully tinted, for busy backgrounds and Reduce Transparency. ![A pill toolbar with share, heart and more buttons and a round plus button, over a light wallpaper. The wallpaper stays fully visible through the glass, bent at the edges, with a bright rim.](https://www.appetiteui.com/images/docs/effects-glass-clear-light.webp) Clear. Ultra clear: content shows through, refraction and rim light only. ![The same toolbar over the light wallpaper, frosted: the wallpaper is blurred behind the pill and the round button, and the edge is clearly drawn.](https://www.appetiteui.com/images/docs/effects-glass-regular-light.webp) Regular. The default: frosted, with a defined edge. ![The same toolbar over the light wallpaper, tinted: the pill and the round button are almost opaque light gray, and the wallpaper barely shows through.](https://www.appetiteui.com/images/docs/effects-glass-tinted-light.webp) Tinted. Fully tinted, for busy backgrounds and Reduce Transparency. Light or Dark comes from the Color Tokens mode of the frame. The glyphs follow that mode whatever sits behind the glass. | Style | Refraction | Frost | Dispersion | Light | Tint token | | --- | --- | --- | --- | --- | --- | | `liquidGlass/Clear` | 0.8 | 2 | 0.25 | 0.35 | `glass/tint-clear`, white at 6% Light, white at 8% Dark | | `liquidGlass/Regular` | 0.7 | 6 | 0.2 | 0.25 | `glass/tint-regular`, white at 32% Light, #4D4D52 at 45% Dark | | `liquidGlass/Tinted` | 0.6 | 12 | 0.15 | 0.25 | `glass/tint-tinted`, #F7F7FA at 86% Light, #38383D at 86% Dark | All three share depth 30, splay 0.2 and a light angle of 0. Each adds the same three layers on top of the glass: a lift shadow (`glass/lift`, black at 4% Light and 24% Dark, offset 8, blur 15), an edge shade one point wide (`glass/edge-shade`, black at 8% Light and 50% Dark) and a rim light one point down (`glass/rim-light`, white at 75% Light and 28% Dark), with the tint of its own stop between them. Put the style on the background layer of the element, never on a frame that holds the content. On a frame with content it recolors the children too. The glass is a GLASS effect in Figma, which bends what sits behind it as well as blurring it. Use liquidGlass in the file, reach for the platform's own glass material in code, and treat the token as a Figma instruction rather than a web spec. CSS has no refraction, so the web has nothing for these styles to differ by. The Tokens table marks every glass layer as having no equivalent, and that is the result. ## What does the focus ring look like? A 2 pt gap in the surface color, then a 2 pt ring in brand/base. Destructive controls take the same ring in state/error/base-500. Specimen: focusRing/brand and focusRing/error. 2 gap in bg/white-0, 2 ring, on the control shape. The ring is two stacked drop shadows with no blur, which is the same as box-shadow: 0 0 0 2px. It follows any corner radius and takes no room in the layout. Apply it to the node that draws the control: the box of a checkbox, the dot of a radio, the track of a toggle. Never apply it to the hit-area frame around the control. That frame stays 44 pt on iOS and 48 dp on Android (`platform/min-touch-target`), and the ring does not grow it. In dark the gap takes the dark surface (`bg/white-0` is #0E0E0F there) and the ring takes `brand/base` in its Dark value, #2B7FFF, so it still reads. | Style | Gap | Ring | Light | Dark | | --- | --- | --- | --- | --- | | `focusRing/brand` | `bg/white-0` | `brand/base` | #FFFFFF, #155DFC | #0E0E0F, #2B7FFF | | `focusRing/error` | `bg/white-0` | `state/error/base-500` | #FFFFFF, #FB2C36 | #0E0E0F, #FB2C36 | ## Tokens All 16 effect styles. Shadow offsets read x y blur spread in pt, and every shadow layer is pure black at the stated alpha unless a token is named. | Token | Value | On the web | | --- | --- | --- | | `dropShadow/xs` | 0 1 2 spread 0, 4% and 0 4 4 spread 0, 1% | box-shadow, layer for layer | | `dropShadow/sm` | 0 9 10 spread -2, 3% and 0 3 5 spread -2, 5% | box-shadow, layer for layer | | `dropShadow/md` | 0 10 15 spread -3, 5% and 0 4 6 spread -4, 8% | box-shadow, layer for layer | | `dropShadow/lg` | 0 12 18 spread -3, 8% and 0 5 6 spread -5, 5% | box-shadow, layer for layer | | `dropShadow/xl` | 0 14 20 spread -5, 8% and 0 6 10 spread -5, 10% | box-shadow, layer for layer | | `dropShadow/2xl` | 0 25 30 spread -6, 12% and 0 8 10 spread -6, 12% | box-shadow, layer for layer | | `dropShadow/edge` | 6 0 12 spread -4, 8% | box-shadow, one layer | | `backdropBlur/sm` | radius 8 | Approximated, blur(8px) | | `backdropBlur/md` | radius 16 | Approximated, blur(16px) | | `backdropBlur/lg` | radius 24 | Approximated, blur(24px) | | `backdropBlur/xl` | radius 40 | Approximated, blur(40px) | | `liquidGlass/Clear` | frost 2, refraction 0.8, depth 30, dispersion 0.25 | No equivalent | | `liquidGlass/Regular` | frost 6, refraction 0.7, depth 30, dispersion 0.2 | No equivalent | | `liquidGlass/Tinted` | frost 12, refraction 0.6, depth 30, dispersion 0.15 | No equivalent | | `focusRing/brand` | 0 0 0 spread 2 `bg/white-0`, 0 0 0 spread 4 `brand/base` | box-shadow, two layers | | `focusRing/error` | 0 0 0 spread 2 `bg/white-0`, 0 0 0 spread 4 `state/error/base-500` | box-shadow, two layers | | Appetite UI style | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | `dropShadow/xs` to `2xl` | No named shadow ramp | Elevation levels, drawn as shadow and tonal surface | One ramp for both platforms, with the same values in Brand and System mode. | | `liquidGlass/*` | Liquid Glass, on the iOS 27 transparency slider | None, Material 3 has no glass | Appetite UI fixes three stops of the slider as styles. Refraction and frost exist in Figma only. | | `focusRing/*` | The system focus ring shown with a hardware keyboard | A state layer at 10% opacity (`M3/sys/state/focus`) | Appetite UI draws a 2 pt gap and a 2 pt ring on both platforms, where Material tints the control. | --- --- title: Motion description: Appetite UI motion tokens for Figma: five durations, five easing curves, three springs and seven presets, with the timing of 14 components. group: Foundations source: https://www.appetiteui.com/docs/motion dateModified: 2026-10-03 --- # Motion Updated: October 3, 2026. Five durations, five curves and three spring configurations. Seven presets alias them, so a sheet, a dialog and a toast move the same way in every screen and in the code. ## How long should a transition take? 120 ms for a small state change, 200 ms for a sheet, a dialog or a page push, 320 ms for progress and 480 ms for a skeleton loop. Click a row to run that one on its own. Figure: the motion tokens in group 0, played on a track. | Token | Value, ms | Used by | | --- | --- | --- | | `motion/duration/instant` | 0 | No component | | `motion/duration/fast` | 120 | Sheet exit, toast enter, toggle state, Table sort, Spinner steps | | `motion/duration/base` | 200 | Sheet enter, dialog enter, page push, Segmented Control, Tabs, Typing Indicator | | `motion/duration/slow` | 320 | Progress Bar, Progress Ring | | `motion/duration/slower` | 480 | Skeleton pulse | No preset reads instant. Progress Bar and Progress Ring read slow directly, so a component can name a duration without a preset, and the Components section below lists who reads what. ## Which easing curve fits which movement? Decelerate for what enters, accelerate for what leaves, standard for small changes that stay put, emphasized for hero moves and linear for loops. Duration says how long, easing says where the time goes. Figure: the motion tokens in group 1, played on a track. | Token | Value | Used by | | --- | --- | --- | | `motion/easing/linear` | cubic-bezier(0, 0, 1, 1) | Skeleton pulse, Spinner, Typing Indicator | | `motion/easing/standard` | cubic-bezier(0.2, 0, 0, 1) | Toggle state, Segmented Control, Tabs, Table sort | | `motion/easing/decelerate` | cubic-bezier(0, 0, 0, 1) | Sheet enter, toast enter | | `motion/easing/accelerate` | cubic-bezier(0.3, 0, 1, 1) | Sheet exit | | `motion/easing/emphasized` | cubic-bezier(0.05, 0.7, 0.1, 1) | Dialog enter, page push, Progress Bar, Progress Ring | decelerate and accelerate are a pair: a thing arriving slows into place, a thing leaving speeds away. emphasized is the steepest curve off the line, with about 78 percent of the distance covered in the first fifth of the time and then a long settle, which is why it carries the dialog and the page push. Never use linear for an entrance. ## How do the three springs behave? Three configurations, stated as response, damping and mass. Native code takes them as springs; on the web, sample the spring into a CSS linear() curve and run it over its response. | Token | Response | Damping | Mass | | --- | --- | --- | --- | | `motion/spring/subtle` | 0.30 | 0.90 | 1.0 | | `motion/spring/default` | 0.40 | 0.80 | 1.0 | | `motion/spring/bouncy` | 0.50 | 0.65 | 1.0 | subtle carries motion/toast/enter and motion/toggle/state. default carries motion/sheet/enter and motion/dialog/enter. bouncy is referenced by no preset, so it is there for a component that asks for it directly. Mass is 1.0 on all three, and response and damping are the only two things that move. A spring on the web, motion/spring/subtle as CSS linear(). ``` /* motion/spring/subtle: response 0.30, damping 0.90. Run it over its response, 300 ms. */ .toggle-handle { transition: transform 300ms linear( 0, 0.0419 3.57%, 0.139 7.14%, 0.2596 10.71%, 0.3843 14.29%, 0.5017 17.86%, 0.606 21.43%, 0.695 25%, 0.7685 28.57%, 0.8277 32.14%, 0.8742 35.71%, 0.9101 39.29%, 0.9372 42.86%, 0.9573 46.43%, 0.9719 50%, 0.9822 53.57%, 0.9894 57.14%, 0.9943 60.71%, 0.9975 64.29%, 0.9995 67.86%, 1.0006 71.43%, 1.0012 75%, 1.0015 78.57%, 1.0015 82.14%, 1.0014 85.71%, 1.0012 89.29%, 1.0011 92.86%, 1.0009 96.43%, 1 ); } ``` The curve is the spring the Figma file plays, sampled at 29 points. subtle peaks at 1.0015 and default overshoots to 1.0152, which is the settle of a sheet or a dialog; the animated components below run both this way. ## Which motion presets does the kit ship? Seven presets, every one an alias. A preset holds no value of its own, it points at a duration, a curve and, where the platform can spring, a spring. Figure: the motion tokens in group 2, played on a track. | Preset | Duration | Easing | Spring | | --- | --- | --- | --- | | `motion/sheet/enter` | base | decelerate | default | | `motion/sheet/exit` | fast | accelerate | None | | `motion/dialog/enter` | base | emphasized | default | | `motion/toast/enter` | fast | decelerate | subtle | | `motion/toggle/state` | fast | standard | subtle | | `motion/page/push` | base | emphasized | None | | `motion/skeleton/pulse` | slower | linear | None | There is no motion/dialog/exit. Sheet ships both directions and dialog ships only enter, so the exit of a dialog has no token yet. ## Which components move, and how? The 14 components that move each name the preset they take their timing from, so retiming a preset retimes every component that reads it. Figure: the motion tokens in group 3, played on a track. | Component | Trigger | Preset | Timing | | --- | --- | --- | --- | | [Accordion](https://www.appetiteui.com/docs/accordion) | Click | `motion/duration/base` | 200 ms, ease out | | [Button](https://www.appetiteui.com/docs/button), loading | Loop | `motion/skeleton/pulse` | 600 ms, ease in out | | [Checkbox](https://www.appetiteui.com/docs/checkbox) | Click | `motion/toggle/state` | 120 ms, standard | | [Dynamic Island](https://www.appetiteui.com/docs/ios) | Press | `motion/dialog/enter` | 320 ms, emphasized | | [Progress Bar](https://www.appetiteui.com/docs/progress) | Loop | `motion/duration/slow` | 320 ms, emphasized, 600 ms dwell | | [Progress Ring](https://www.appetiteui.com/docs/progress) | Loop | `motion/duration/slow` | 320 ms, emphasized, 600 ms dwell | | [Radio](https://www.appetiteui.com/docs/radio) | Click | `motion/toggle/state` | 120 ms, standard | | [Segmented Control](https://www.appetiteui.com/docs/segmented-control) | Click | `motion/duration/base` | 200 ms, standard | | [Skeleton](https://www.appetiteui.com/docs/skeleton) | Loop | `motion/skeleton/pulse` | 480 ms, linear | | [Spinner](https://www.appetiteui.com/docs/progress) | Loop | `motion/duration/fast` | 80 ms per step, linear, 8 steps | | [Table](https://www.appetiteui.com/docs/table), sort | Press | `motion/duration/fast` | 120 ms, standard | | [Tabs](https://www.appetiteui.com/docs/tab) | Click | `motion/duration/base` | 200 ms, standard | | [Toggle](https://www.appetiteui.com/docs/toggle) | Click | `motion/toggle/state` | 120 ms, standard | | [Typing Indicator](https://www.appetiteui.com/docs/progress) | Loop | `motion/duration/base` | 200 ms, linear, 100 ms dwell | The Timing column is what each component animates with in the Figma file. The collection holds 31 variables, and every component that moves reads from it. ## Which components animate their own state change? The Motion page holds 9 sets that play their own transition on the Figma timeline. Each has one-shot variants and a Loop for presentations, all timed from the presets above. Place an instance in a top-level frame and press play. Use a one-shot variant in a prototype and Loop on a cover or in a presentation. One-shot variants start at 0.2 s. Loop plays the change at 0.4 s and back at 1.4 s, so a 2 s timeline loops cleanly, and the drawings above play the Loop variants that way. | Component | Variants | What moves | Timing | | --- | --- | --- | --- | | Toggle | Turn on, Turn off, Loop | The handle travels 16, Track on fades in | Handle `motion/toggle/state/spring`, subtle, 300 ms. Track 120 ms, standard | | Checkbox | Check, Uncheck, Loop | The box scales in from 0.8 and the mark draws itself; Uncheck fades both | Box spring subtle, 300 ms. Fill and mark 120 ms, standard | | Radio | Select, Deselect, Loop | The ring fills and the dot springs in from 0.4 | Dot spring subtle, 300 ms. Ring 120 ms, standard | | Button | Tap, Loop | Scales to 96 percent and darkens on press, springs back on release | Press `motion/duration/fast` and `motion/easing/standard`, 120 ms. Release `motion/spring/subtle` | | Toast | Enter, Exit, Loop | Enter drops 24 and fades in, Exit lifts 12 and fades out | Enter position spring subtle, opacity 120 ms decelerate. Exit 120 ms, accelerate | | Dialog | Enter, Exit, Loop | The card scales in from 0.92 over a scrim, and out to 0.96 | Enter scale `motion/dialog/enter/spring`, default, 400 ms, opacity 200 ms emphasized. Exit 120 ms, accelerate | | Sheet | Enter, Exit, Loop | The sheet rises 387 over a scrim | Enter sheet spring default, 400 ms, scrim 200 ms decelerate. Exit 120 ms, accelerate | | Page Push | Push, Pop, Loop | The new screen slides in from the trailing edge, the old one shifts 30 percent and dims | `motion/page/push`, 200 ms, emphasized | | Skeleton | One component | Three list rows pulse between 100 and 40 percent | `motion/skeleton/pulse`, 480 ms each way, linear, two cycles in 1.92 s | Every chart except Legend animates on the same timeline. Bar raises each column 12 from a fade over 480 ms, 50 ms apart, and Line draws its current series over 600 ms on standard. Eight example screens enter in reading order, in Light and Dark. ## What should motion do when Reduce Motion is on? Swap the movement for a fade or an instant change and keep the state change. With Reduce Motion on, the Play buttons on this page move the dot to the end of the track without animating it. A sheet still opens, a toggle still flips and a toast still appears. What goes is the travel: a slide, a scale or a spring becomes a fade at the same duration or a cut, so the new state is visible without the reader being moved across the screen. Looping motion such as Skeleton pulse and Spinner stops on a still frame. The animated components above rest on their end state the same way, and their Pause button stops the loop at any time. --- --- title: Platform Bridge description: Platform Bridge maps 53 Apple and 60 Material 3 slots to your brand tokens, and one mode switch returns the platform's own values. group: Foundations source: https://www.appetiteui.com/docs/platform-bridge dateModified: 2026-10-04 --- # Platform Bridge Updated: October 4, 2026. Platform Bridge lets one screen carry your brand or the platform's own look. 113 variables on two modes: Brand resolves an Apple or Material 3 role to an Appetite UI token, System returns the value Apple or Google publishes. One dropdown moves a whole screen. ## How do I design one app for iOS and Android? Set the Platform Bridge mode on a frame to Brand and every Apple and Material 3 slot reads an Appetite UI token, so one brand edit moves both platforms. Set it to System and the same slots return the values Apple and Google publish. The mode decides where a component reads its value from. Appetite UI names the slots of the Apple and Material design systems and points each one at a token you control: 113 slots, 53 from Apple and 60 from Material, covering color, shape and type size. | Slot group | Slots | Brand mode reads | System mode reads | | --- | --- | --- | --- | | iOS color roles | 34 | Color Tokens, semantic | `platform/ios/*` | | iOS shape | 7 | `dimensions/radius/*` | Apple's own radii | | iOS type size | 12 | `typography/fontSize/*` | Dynamic Type at Large | | Material color roles | 32 | Color Tokens, semantic | `platform/m3/*` | | Material shape | 6 | `dimensions/radius/*` | Material's own radii | | Material state opacity | 7 | a bare number | the same number | | Material type size | 15 | `typography/fontSize/*` | published typescale | ## What does Brand mode do? In Brand mode a platform slot stops being a color and becomes a pointer. iOS/tintColor points at brand/base, which points at colors/blue/500, and that primitive is the only place the hex is written down. M3/sys/color/primary ends on the same primitive, so one edit moves an iOS screen and an Android screen together. Figure: the Platform Bridge chain, step 1. | Platform slot | Resolves through | Brand value | | --- | --- | --- | | `iOS/label` | | #0E0E0F | | `M3/sys/color/on-surface` | | #0E0E0F | | `iOS/systemRed` | | #FB2C36 | | `M3/sys/color/error` | | #FB2C36 | | `iOS/secondaryLabel` | | #48484A | | `iOS/separator` | | #E9E9EA | | `M3/sys/color/tertiary` | | #155DFC | In Brand mode `M3/sys/color/tertiary` resolves to the same `brand/base` as primary, so the two roles share one color until you point tertiary somewhere else. 102 of the 113 slots resolve to an Appetite UI token in Brand mode. The other 11 hold a platform value or a bare number in both modes, and they are listed in the section on slots the switch does not move. ## How do I return a screen to the native look? Switch the Platform Bridge mode on the frame to System. Every slot drops its pointer and returns the value Apple and Google publish, so the screen stops being yours and becomes theirs. That is the view a native review asks to see. Nothing is approximated. Those values sit in Color Tokens as 67 untouched platform primitives, stored once and never retyped into a component. It is one switch on the frame. | Platform slot | Brand mode | System mode | Published as | | --- | --- | --- | --- | | `iOS/tintColor` | #155DFC | #007AFF | systemBlue | | `iOS/secondaryLabel` | #48484A | #3C3C43 at 60% | secondaryLabel | | `iOS/separator` | #E9E9EA | #3C3C43 at 18% | separator | | `iOS/systemGray` | #8E8E93 | #8E8E93 | systemGray | | `M3/sys/color/primary` | #155DFC | #6750A4 | Material baseline primary | A few slots land on the same value in both modes without being wired that way. The Appetite UI gray scale and Apple's systemGray already agree at #8E8E93. ## Which type sizes does the Bridge carry? The Bridge carries type size as well as color. 12 iOS text styles and 15 Material typescale steps each point at an Appetite UI step in Brand mode and return the platform's own published size in System mode. Only the size step is carried, and weight, line height and letter spacing stay on the Appetite UI side. | Step | Brand points at | Brand | System | | --- | --- | --- | --- | | `iOS/sys/typography/largeTitle` | `fontSize/4xl` | 36 | 34 | | `iOS/sys/typography/title2` | `fontSize/xl` | 20 | 22 | | `iOS/sys/typography/headline` | `fontSize/lg` | 18 | 17 | | `iOS/sys/typography/body` | `fontSize/lg` | 18 | 17 | | `iOS/sys/typography/subheadline` | `fontSize/sm` | 14 | 15 | | `iOS/sys/typography/footnote` | `fontSize/xs` | 12 | 13 | | `iOS/sys/typography/caption2` | `fontSize/xs` | 12 | 11 | | `iOS/sys/typography/tabBarLabel` | `fontSize/xs` | 12 | 10 | | `M3/sys/typescale/display-large` | `fontSize/6xl` | 60 | 57 | | `M3/sys/typescale/headline-large` | `fontSize/3xl` | 30 | 32 | | `M3/sys/typescale/title-large` | `fontSize/xl` | 20 | 22 | | `M3/sys/typescale/label-small` | `fontSize/xs` | 12 | 11 | The Appetite UI scale is coarser than either platform ramp, so steps collapse in Brand mode. iOS headline and body both land on `fontSize/lg`, and footnote, caption1, caption2 and tabBarLabel all land on `fontSize/xs`. Distinctions Apple draws a point apart do not survive the switch. `iOS/sys/typography/tabBarLabel` is Apple's 10 pt tab label in System mode. ## Which slots does the mode switch not move? Fourteen slots are wired to the same source in both modes. Eleven are the ones counted out of the 113 under Brand mode, and the switch cannot reach them. Three run the other way: they take an Appetite UI token like the other 102, then keep it. | Slots | Count | Value in both modes | | --- | --- | --- | | `M3/sys/state/*` | 7 | Bare numbers: hover 8, focus 10, pressed 10, dragged 16, disabled 38 and 12, scrim 32. | | `iOS/glassControl``iOS/segmentSelected``iOS/glassClear``iOS/glassBorderDark` | 4 | An Apple value in Brand mode too. The last is a bare white at 12%, written into the variable itself. | | `iOS/glassBorder``iOS/glassEdge``iOS/glassShadow` | 3 | An Appetite UI glass token in System mode too, because Apple publishes no value for them to return to. | ## What do the five Platform modes do? A frame picks one of five Platform modes, ios-md, ios-lg, android, ios-duo-outer or ios-duo-inner, and the same component then reads a 44 pt touch target on iOS and 48 dp on Android from one variable. Platform is a second collection beside this one: its 20 variables carry geometry such as touch targets, safe areas and corners. Two of the modes and four of the variables serve iPhone Duo. | Variable | ios-md | ios-lg | android | ios-duo-outer | ios-duo-inner | | --- | --- | --- | --- | --- | --- | | `grid/safe-area/top` | 59 | 62 | 52 | 24 | 24 | | `grid/safe-area/bottom` | 34 | 34 | 24 | 24 | 24 | | `grid/safe-area/trailing` | 0 | 0 | 0 | 96 | 96 | | `grid/columns` | 4 | 4 | 4 | 4 | 6 | | `platform/min-touch-target` | 44 | 44 | 48 | 44 | 44 | | `platform/bar/top-height` | 44 | 44 | 64 | 44 | 44 | | `platform/bar/bottom-height` | 49 | 49 | 64 | 0 | 0 | | `platform/list-row/min-height` | 44 | 44 | 56 | 44 | 44 | | `platform/control/corner` | 8 | 8 | 9999 | 8 | 8 | | `platform/card/corner` | 12 | 12 | 12 | 12 | 12 | | `platform/sheet/corner` | 12 | 12 | 28 | 12 | 12 | | `platform/dialog/corner` | 12 | 12 | 28 | 12 | 12 | | `platform/switch/track-width` | 64 | 64 | 52 | 64 | 64 | | `platform/switch/track-height` | 28 | 28 | 32 | 28 | 28 | | `platform/screen-padding` | 16 | 16 | 16 | 16 | 16 | | `platform/duo/sidebar-width` | 0 | 0 | 0 | 0 | 262 | | `platform/duo/device-corner` | 48 | 48 | 48 | 48 | 48 | | `platform/duo/pane-corner` | 26 | 26 | 26 | 26 | 26 | | `platform/font/brand`, `platform/font/system` | Inter | Inter | Inter | Inter | Inter | `grid/columns` is 4 on every mode except ios-duo-inner, which has 6, the same counts as the five grid styles on the [Dimensions page](https://www.appetiteui.com/docs/dimensions#grids). ios-md and ios-lg differ in exactly one variable, `grid/safe-area/top`, at 59 and 62. The two Duo modes are for iPhone Duo screens: ios-duo-outer for the outer display and ios-duo-inner for the inner one. They differ in two variables: `grid/columns`, 4 on the outer display and 6 on the inner, and `platform/duo/sidebar-width`, 0 outside and 262 inside, where a sidebar stands beside the content. Both modes take the bars off the horizontal axis. The safe areas at the top and the bottom are 24, `platform/bar/bottom-height` is 0, and `grid/safe-area/trailing` is 96, the room of the vertical control rail that carries the status bar, toolbar and tab bar. The device corner of 48 and the pane corner of 26 sit in every mode. On the touch target: `platform/min-touch-target` is 44 in the four iOS modes and 48 in android, so one component obeys both without a second copy. --- --- title: Assets description: The Appetite UI Figma file ships brand marks, flags, emoji, store badges and placeholder company logos as components, so one swap reaches every screen. group: Foundations source: https://www.appetiteui.com/docs/assets dateModified: 2026-10-03 --- # Assets Updated: October 3, 2026. The stock artwork a mock-up needs before it looks real: brand marks, country flags, emoji, store badges and placeholder company logos, all of them components, so one swap reaches every screen. Use them to make a screen look finished, then replace the third party marks before you ship. ![A grid of Apple emoji that ships in the file: faces, hands, hearts, animals, food, places and activities, all drawn at one size on a white ground.](https://www.appetiteui.com/images/docs/assets-emoji.webp) ## What assets ship in the file? Six families: the Appetite UI logo, brand marks, country flags, emoji, store badges and Company Logo. Every one is a component, so a swap reaches every screen that uses it at once. | Family | Count | What it is | Owner | | --- | --- | --- | --- | | Appetite UI logo | 2 | Symbol and lockup, vector, fill bound to a color variable | Ours | | Company Logo | 48 | One set, 12 placeholder companies as a symbol or a lockup, in Color or Mono, 32 high | Ours, invented companies | | Brand marks | 205 | 14 groups, 32 x 32 vector, one component each | Third party | | Country flags | 262 | One set, circular, 24 x 24 vector | Third party | | Emoji | 586 | One set, 24 x 24, raster fill, not vector | Third party | | Store badges | 8 | One set, 4 stores in 2 styles, 40 high | Third party | | Set | Property | Options | | --- | --- | --- | | Logo | Style | Logo, Symbol | | Company Logo | Company | Halcyon, Orbital, Lumen, Pinpoint, Sundial, Relay, Stacks, Northwind, Bloom, Mosaic, Tidal, Keystone | | Company Logo | Type | Symbol, Lockup | | Company Logo | Style | Color, Mono | | Country Flags | Flag | 262 country and region names, from Abkhazia to Zimbabwe | | Emojis | Emoji | 586 names that follow Emojipedia, from 1st Place Medal to Zzz | | App Store Badges | Company | App Store, Galaxy Store, Google Play Store, Microsoft Store | | App Store Badges | Style | Alternative, Preferred | The Assets page of the file holds 1,111 components in all: the logo set, 205 loose brand marks, and the four sets of flags, emoji, store badges and Company Logo. Together they make five component sets and the loose brand marks. Brand marks are standalone components, so they do not count as variants. ## Which brand marks are in the file? 205 marks of apps and services people actually use, in 14 groups. They are glyphs only, with no wordmarks, so they stay readable at icon size. | Group | Marks | | --- | --- | | Major Brands | 24 | | Google Brands | 36 | | Microsoft Brands | 12 | | Adobe Brands | 17 | | Social Media | 12 | | Browsers | 6 | | Payments | 5 | | Design Tools | 16 | | Developer | 16 | | Productivity | 16 | | Commerce and Crypto | 12 | | Travel and Local | 9 | | Marketing and Analytics | 14 | | Content and Publishing | 10 | Every mark is one component of 32 by 32, so a swap with the instance menu keeps the layout. ## What are the Company Logo placeholders for? Company Logo is a set of twelve invented companies for mock-ups that need a plausible customer, employer or app behind a screen. Each company comes as a symbol or a lockup, in color or mono. ![Twelve placeholder companies, each drawn as a symbol and as a lockup with its name, in color on the left and in black mono on the right: Halcyon, Orbital, Lumen, Pinpoint, Sundial, Relay, Stacks, Northwind, Bloom, Mosaic, Tidal and Keystone.](https://www.appetiteui.com/images/docs/assets-company-logo.webp) Company Logo, Type Symbol and Lockup, Style Color and Mono. Mono follows the Color Tokens mode: its fills read `fg/strong-950`, #0E0E0F in Light and #FFFFFF in Dark, so one component serves both modes. The Dynamic Island and Finance screens use the set for the apps and companies they show. ## Who owns the marks, and what do I replace? You replace every third party mark before you ship. The Appetite UI logo and the Company Logo placeholders are ours, and everything else belongs to its owner. Every third party mark in the file carries the same component description: marks are owned by their respective companies, they must not be recolored or redrawn, and you check the provider's brand guidelines before you ship. Use them to populate a realistic mock-up, then replace them. The twelve Company Logo placeholders are invented companies, not third party marks. Country flags, emoji and store badges follow the third party rule. --- --- title: Code output description: One W3C DTCG token source generates CSS, SwiftUI, Jetpack Compose and Flutter, and a coding agent reads the same names. How to use the outputs. group: Foundations source: https://www.appetiteui.com/docs/code-output dateModified: 2026-10-04 --- # Code output Updated: October 4, 2026. One token source generates CSS, SwiftUI, Compose and Flutter. The same file is what a coding agent reads, so the name in the design and the name in the code are the same name. ## How does one variable become four languages? Appetite UI holds its values once, as a token file, and generates the rest. One variable, four languages, no second copy to keep in step. Specimen: brand/base, from one variable to four generated names. 6 collections, 2 modes on color, 1 source file. The export reads the first three names off the variable, which stores a code name for web, iOS and Android. ## What is the token source? One JSON file in the W3C Design Tokens format, run through Style Dictionary v5. Primitives hold the values. Semantic tokens point at primitives. Nothing holds a value twice. The token file, two entries, one reference. ```json { "colors": { "blue": { "500": { "$type": "color", "$value": "#155DFC" } } }, "brand": { "base": { "$type": "color", "$value": "{colors.blue.500}" } } } ``` | Collection | Variables | Modes | | --- | --- | --- | | `Foundations` | 202 | Default | | `Color Tokens` | 190 | Light, Dark | | `Typography` | 33 | Default | | `Motion` | 31 | Default | | `Platform` | 20 | ios-md, ios-lg, android, ios-duo-outer, ios-duo-inner | | `Platform Bridge` | 113 | Brand, System | Figma writes a path with slashes, `brand/base`. The token file writes the same path with dots, so the reference reads `{colors.blue.500}`. Same token, two notations, and the export is where they meet. The format is a public standard, so other design token tools can read the same values. ## Which languages does the export produce? Four outputs off the one source. These are examples of what the export produces, cut to three tokens so the four sit side by side: a color, a spacing step and a duration. CSS custom properties, web. ```css :root { --ap-brand-base: #155DFC; --ap-space-4: 16px; --ap-duration-fast: 120ms; } ``` SwiftUI, iOS. ```swift extension Color { static let apBrandBase = Color.apDynamic( light: Color(apHex: 0x155DFC), dark: Color(apHex: 0x2B7FFF)) } enum AppetiteSpacing { static let space4: CGFloat = 16 } enum AppetiteMotion { static let durationFast = 0.12 } ``` Jetpack Compose, Android. ```kotlin internal val BrandBase = Color(0xFF155DFC) internal val Space4 = 16.dp internal val DurationFast = 120 // read as AppetiteTheme.colors.brandBase ``` Flutter, Dart. ```dart const apBrandBase = Color(0xFF155DFC); const apSpace4 = 16.0; const apDurationFast = Duration(milliseconds: 120); ``` The file has no slot for Dart, so the export derives the Flutter names above. The other three are read off the variables. The SwiftUI output emits Dynamic Type anchors for its text sizes, and the Compose output includes a ready Material 3 typography object. The Flutter output builds ThemeData for Light and Dark with `AppetiteTheme.light()` and `AppetiteTheme.dark()`. The source also carries the chart series colors, `bg/raised`, the glass tokens, the radius steps of 40 and 48, the Duo platform variables, and the heading family `typography/fontFamily/Heading`, Inter Display. ## How do I use the tokens in my project? Take the source and the four outputs that come with the file you buy, add the output for your platform to the project, and use the generated names. There is no package to install and no public repository. The table gives the color and the spacing step of the samples above in each output. | Output | brand/base | spacing/4 | | --- | --- | --- | | CSS | `var(--ap-brand-base)` | `var(--ap-space-4)` | | SwiftUI | `Color.apBrandBase` | `AppetiteSpacing.space4` | | Jetpack Compose | `AppetiteTheme.colors.brandBase` | `AppetiteTheme.spacing.space4` | | Flutter | `apBrandBase` | `apSpace4` | ## How do modes reach the code? A mode is a second value on the same token, in the same file. Light and Dark on color, Brand and System on the platform mirrors, five Platform modes on the platform metrics. One source carries all of them. | Token | Mode | Resolves to | Value | | --- | --- | --- | --- | | `brand/base` | Light | colors/blue/500 | #155DFC | | `brand/base` | Dark | colors/blue/400 | #2B7FFF | | `text/on-color/strong` | Light | static/static-white-0 | #FFFFFF | | `text/on-color/strong` | Dark | static/static-white-0 | #FFFFFF | | `M3/sys/color/primary` | Brand | brand/base | #155DFC | | `M3/sys/color/primary` | System | platform/m3/primary | #6750A4 | | `platform/min-touch-target` | ios-md, ios-lg, ios-duo-outer, ios-duo-inner | the value itself | 44 | | `platform/min-touch-target` | android | the value itself | 48 | The on-color tokens resolve to white in both modes. A label on a filled button keeps its color when the theme flips. The last two rows are the minimum touch target: 44 pt on iOS and 48 dp on Android, read from one variable. What the CSS export does with two modes, one name, two values. ```css :root { --ap-brand-base: #155DFC; } [data-theme="dark"], .dark { --ap-brand-base: #2B7FFF; } @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]):not(.light) { --ap-brand-base: #2B7FFF; } } ``` ## Can a coding agent read the design system? Yes. The Appetite UI Core Skill is an instruction file included with your purchase. It teaches a coding agent which token and which pattern to use, so Claude, Cursor or anything else that reads project instructions works from the same source the export runs on. Figure: What a variable says about itself. Those descriptions are carried on the variables themselves: the guidance travels with the value. Figma Code Connect maps one component to one snippet. An agent also has to know which token to reach for, and that is what the Core Skill supplies. --- --- title: Accordion description: An accordion row hides a block of text under its title until someone taps it. Appetite UI Figma component: three states, icon option, tokens, iOS notes. group: Components source: https://www.appetiteui.com/docs/accordion dateModified: 2026-10-03 --- # Accordion Updated: October 3, 2026. Accordion hides an answer or a detail under a one-line title until someone taps the row, so a long screen stays short. ## Preview A row that opens in place, for FAQ lists and grouped settings: closed it shows the title, open it adds the description underneath. Live specimens, open one. Specimen: Accordion, State Default and Active. 340 wide, 56 tall closed, padding 16, gap 12. Every row is one component with one hidden text node: the description sits under the title in every variant and switches off while the row is closed. A closed row hugs to 56, 16 of padding, 24 of title and 16 of padding, at a pinned width of 340. Accordion ships 6 variants, State by Icon. Source: the Accordion set of the Appetite UI Figma file, read on October 2, 2026. ## Which states does Accordion have? Three states on one shape: Default is bg/white-0 with a 1 border/soft-100 edge and a shadow, and Pressed drops both and fills bg/weak-50. Active keeps that fill and opens the description. Specimen: State Default, Pressed, Active. radius 24 in all three, edge and shadow on Default only. All three states share one radius, 24, so the row keeps its shape as it opens. Only the fill, the edge and the shadow change. Default is the only state with the inside edge and the xs shadow, a 2 blur one down at 4 percent and a 4 blur four down at 1. Pressed and Active are flat. The chevron is swapped, not turned: chevron-down while closed, chevron-up when open. With the file's description text, Active is 102 tall, with the icon and without it. The description wraps to two lines in the 236 column and in the 272 column, so a longer text makes the row taller and leaves the padding alone. The prototype presses Default into Pressed, then moves Pressed and Active to the next state on click. It runs 200 ms on ease out, motion/duration/base in the Motion collection. ## How do I add a leading icon? Set Icon to True; it is off by default. A 24 box holding a 20 vector at stroke 2 then leads the row, and the text column narrows by 36, the icon plus the 12 gap. Specimen: Icon True, Icon False. 24 box, 20 vector, stroke 2, fg/sub-700. The chevron stays at the right end of the row when the icon is off. The chevron is the one part that changes color with State: fg/soft-500 while closed, fg/sub-700 the moment you touch the row or open it. The leading icon holds fg/sub-700 throughout. Both sit in a 24 box, but the leading glyph draws at 20 and the chevron at 12 by 6. ## Properties Two variant axes, two text properties and an instance swap. | Property | Type | Default | | --- | --- | --- | | `State` | Variant: Default \| Pressed \| Active | Default | | `Icon` | Variant: True \| False | False | | `Title` | Text | Title of accordion | | `Description` | Text, visible in Active only | Body content that appears when the row expands. | | `Icon Swap` | Instance swap | circle-question-mark | Title and Description are both text properties, so a real FAQ row is two overrides. Description is bound to the node that is hidden while the row is closed, so you can fill it on a collapsed instance and see nothing until State goes to Active. The title is Regular 16/24 and the description Regular 14/20, so size and color are all that separate them. The matrix is complete: three states across both Icon values. ## Tokens Every value the component reads, resolved through its aliases to the primitive underneath. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/white-0` | #FFFFFF | #0E0E0F | Default fill | | `border/soft-100` | #E9E9EA | #2F2F31 | The 1px inside edge, Default only | | `bg/weak-50` | #F4F5F5 | #242427 | Pressed and Active fill | | `text/strong-950` | #0E0E0F | #FFFFFF | Title | | `text/sub-700` | #48484A | #C7C7CC | Description | | `fg/sub-700` | #48484A | #C7C7CC | Leading icon, and the chevron in Pressed and Active | | `fg/soft-500` | #8E8E93 | #AEAEB2 | Chevron in Default | Radius is 24, `dimensions/radius/2xl`, in all three states. The shadow on Default is the effect style `dropShadow/xs`, and every color is a semantic token. ## How does Accordion differ on iOS and Material 3? Neither platform has an accordion set in the file. iOS builds it with DisclosureGroup and Android with an expandable list item, and Appetite UI draws one row for both. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Accordion | None in the file. In code, SwiftUI DisclosureGroup. The nearest drawn row is iOS / List with a Chevron trailing slot. | None in the file. In code, an expandable list item. | Appetite UI draws a 340 wide card row, 56 tall closed, with its own radius 24 and shadow. A native list row is 44 tall on iOS and 56 on Android, from platform/list-row/min-height. | The row is 56 tall, above the minimum touch target of 44 pt on iOS and 48 dp on Android in `platform/min-touch-target`. In code, build it on the native disclosure so VoiceOver and TalkBack announce the expanded state. ## When should I use an Accordion? Use a stack of rows when each title has a detail worth hiding, as in FAQ lists and grouped settings. - Do: Stack them. One row alone reads as a button that did nothing, and the list says there is more behind each title. - Avoid: Do not nest one inside another. A reader two levels deep has lost track of what closing does. Keep the title to one line. At 236, the column you get once the leading icon is on, a wrapping title pushes the closed height past 56 and breaks the rhythm of the stack. --- --- title: Action Sheet description: Action Sheet lists the actions for one object at the bottom of the screen. Appetite UI Figma component: radius 48, capsule buttons, a slot and tokens. group: Components source: https://www.appetiteui.com/docs/action-sheet dateModified: 2026-10-03 --- # Action Sheet Updated: October 3, 2026. Action Sheet presents a short list of actions for one object, anchored to the bottom of the screen. ## Preview A bottom anchored list of actions about one object, over a scrim that blocks everything behind it. Live specimen: dismiss it from the close button or the scrim. Specimen: Action Sheet, shipped content. 340 x 396, padding 24 20 20, gap 16, radius 48. The sheet is 396 tall by arithmetic: 24 of top padding, then blocks of 60, 140 and 120 stacked 16 apart, then 20. It hugs, so a fuller slot grows the sheet and leaves padding and gaps alone. The sheet comes in at 200 on decelerate and leaves at 120 on accelerate, the motion/sheet tokens in the Motion collection. The sheet is radius 48 on bg/raised, white in Light and #242427 in Dark, with no stroke. The two actions are capsules, Button at Size lg, 56 tall. The close is a 32 Compact Button at Style Transparent. Give it a 44 pt hit area on iOS and 48 dp on Android in code. Source: Action Sheet, node 124:4488 of the Appetite UI Figma file, read on October 2, 2026. ## What goes in the header of an Action Sheet? The header block carries the message: a 24/32 Semi Bold title and a 16/24 subheadline, 4 apart. The subheadline is a boolean, and without it the block gives back 28. Specimen: Subheadline True, Subheadline False. block 300 x 60, then 300 x 32. The 60 assumes one line of subheadline. Two lines make the block 84 and the sheet 420. ## Which properties does Action Sheet have? No variant axis. Two text properties, one boolean and one slot. | Property | Type | Default | | --- | --- | --- | | `Title` | Text | Title of action sheet | | `Subheadline` | Boolean | true | | `Subheadline Text` | Text | Subheadline of action sheet | | `Content Slot` | Slot | Empty | Action Sheet ships one variant. The two actions are Button instances, so type, style, size and state live on Button. ## Tokens Every value the component reads, resolved through its aliases to the primitive underneath. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/raised` | #FFFFFF | #242427 | Sheet fill | | `text/strong-950` | #0E0E0F | #FFFFFF | Title | | `text/sub-700` | #48484A | #C7C7CC | Subheadline | | `fg/soft-500` | #8E8E93 | #AEAEB2 | Close icon | | `brand/base` | #155DFC | #2B7FFF | Filled fill, Link label | | `static/static-white-0` | #FFFFFF | #FFFFFF | Filled label | | `bg/scrim` | #000000 at 40% | #000000 at 48% | The scrim behind the sheet | Radius is `dimensions/radius/5xl` at 48 on the sheet and `full` on every button, the close included. The shadow is `dropShadow/2xl`, two black layers at 12 percent in both themes. The sheet has no stroke. In dark it separates from the screen by bg/raised alone. ## How does Action Sheet differ on iOS and Material 3? iOS draws its own action sheet and Material 3 has a bottom sheet. Appetite UI Action Sheet is the one cross-platform version, with capsule actions and a slot for your own content. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Action Sheet | iOS / Action Sheet, 300 x 362 at radius 32 on glass, with capsule _Action Button in Secondary and Destructive, padded 14 | M3 / Bottom sheet, Modal False or True, 412 wide | Appetite UI is 340 wide at radius 48 on bg/raised, with a title row, a content slot and Brand buttons. The iOS sheet is a smaller glass card with fixed actions. Material has no action sheet and uses a modal bottom sheet. | On iOS use the system control for the action list and take the type and color from Appetite UI. On Android use a Modal Sheet. The 56 tall actions clear the minimum touch target of 44 pt on iOS and 48 dp on Android, set by `platform/min-touch-target`. ## Guidelines - Do: Put the destructive action last and give it the error tokens. A red row that always sits in the same place is a row people learn to look for. - Avoid: Do not stack four equal actions. A sheet settles one decision about one object, and a list of everything you can do is a menu that goes in the slot. --- --- title: AI description: AI components for mobile apps: a Message row and a Prompt composer with streaming, error and attachment states. Appetite UI for Figma, with tokens. group: Components source: https://www.appetiteui.com/docs/ai-component dateModified: 2026-10-03 --- # AI Updated: October 3, 2026. Message is one row of a conversation, and Prompt composer is the input under it. Together they cover a thread, an answer that is still arriving, an answer that failed, and the five states of the input. ## Preview Two surfaces an AI product cannot borrow from anything else in the system: the conversation row and the prompt input. Everything standing around them, suggestion chips, source cards, the tools menu and the model picker, is Chip, Card, Context Menu and Dropdown. Specimen: Message Role User, Message Role Assistant, Prompt Composer State Empty. thread 361 wide, composer 361 x 96 at radius 32. Source: the AI / Message and AI / Prompt Composer sets of the Appetite UI Figma file, read on October 2, 2026. A thread is a column of Message rows and the composer is pinned under it, so neither component knows what the other holds. The exchange above is sample copy from the example screen, in use on the [AI screens](https://www.appetiteui.com/docs/screens-ai). The three dots under a streaming answer are drawn inside Message. For an indicator that stands on its own, use Typing Indicator on the [Progress](https://www.appetiteui.com/docs/progress) page. ## Which roles and states does Message have? Message has two Roles, User and Assistant, and three States, Default, Streaming and Error. Role decides the shape and State decides what an unfinished answer looks like, so a thread is one component repeated. Specimen: Role User and Role Assistant, both State Default. 361 x 48 and 361 x 24, bubble 280 at radii 20 20 6 20. | Property | Values | What it changes | | --- | --- | --- | | `Role` | User, Assistant | User draws a 280 bubble in bg/soft-100 pushed right. Assistant draws no container and runs the full 361. | | `State` | Default, Streaming, Error | Streaming hangs a 28 x 6 row of three dots under the answer. Error swaps the answer for a 12 radius panel with an icon, a reason and a Retry button. | | `Message` | Text | The body copy, and the only text property the set exposes. It defaults to Message text. | Four of the 6 Role by State cells exist, because a user turn cannot stream or fail. Handle a failed send on the composer or as a Toast. The Retry button is a Button at Type Error, Style Weak and Size sm: a state/error/base-500 label on a red tint at 10 percent. The Answer frame uses gap 8 in Default and gap 12 in Streaming and Error, and the Actions frame under the error carries 30 of left padding to line the button up with the copy. ## Which states does the Prompt composer have? The Prompt composer has five states: Empty, Typing, Generating, Disabled and Attachment. One shell carries all five, and the state says what the input is doing: waiting, ready, working, shut or carrying a file. Specimen: State Empty. 361 x 96, radius 32, padding 16, 1px inside stroke, dropShadow/sm. Empty draws the send disc dormant, bg/soft-100 with an fg/disabled-400 arrow. Typing turns the disc brand/base as soon as the field holds text. Generating clears the field, because the prompt has been sent, and puts Stop on the same disc. Disabled covers offline and over the limit, every glyph on fg/disabled-400 over a bg/weak-50 shell. Attachment puts the file above the prompt with its own remove control. The plus opens the tools menu, a Context Menu instance, so the tool list is not fixed. The shell is padded 16 on every side at radius 32, the same 16 as platform/screen-padding in the Platform collection. It is 96 tall at one line and 157 with a file and grows with its value, so set the ceiling in code. ## Anatomy Every part is measured and written as drawn. Where a value sits off the spacing scale it is written as it stands. | Part | Measured | How it resolves | | --- | --- | --- | | User bubble | 280 wide, padding 12 and 16, radii 20 20 6 20, 48 tall at one line | Fixed 280 in a 361 row aligned right. 16 + 248 + 16 = 280, and the clipped corner is the near one. | | Assistant answer | 361 wide, 24 tall at one line | No frame, no fill. The Answer stack is gap 8 in Default and gap 12 in Streaming and Error. | | Streaming dots | 28 x 6, three dots of 6 at gap 5 | fg/soft-500, 12 under the text. | | Error panel | 361 x 112, padding 12, radius 12 | Row 337 x 40 at gap 10 with a 20 triangle-alert, then a 100 x 36 Retry. Actions carries 30 of left padding, off the scale, to align the button with the copy. | | Composer shell | 361 wide, padding 16, radius 32, gap 8 | Content is 329 in every state. Heights run 96 and 157 with a file. | | Controls row | 329 x 32, gap 8, tools gap 6 | Discs are 32 at radius 9999 holding an 18 glyph at 1.75. Stop is an 11 square at radius 2.5. | | Attachment row | 329 x 53, padding 8 10 8 8, radius 16 | Tile 36 at radius 8, remove 20 and round, meta gap 1. 8 + 36 + 10 + 235 + 10 + 20 + 10 = 329. | Both 1 pt strokes are drawn inside, so a CSS border would make the shell 363 wide and the attachment row 55. Draw them as inset shadows or inside strokes, which add nothing. ## Tokens Nothing on either component carries a raw color. Each token is resolved in Light and Dark. | Where | Token | Light | Dark | | --- | --- | --- | --- | | Composer surface | `bg/white-0` | #FFFFFF | #0E0E0F | | Bubble, discs, tile | `bg/soft-100` | #E9E9EA | #48484A | | Disabled shell | `bg/weak-50` | #F4F5F5 | #242427 | | Remove control | `bg/sub-200` | #D1D1D6 | #636366 | | Both 1 pt strokes | `border/soft-100` | #E9E9EA | #2F2F31 | | Answer, bubble, typed value, file name, paperclip | `text/strong-950`, `fg/strong-950` | #0E0E0F | #FFFFFF | | Plus glyph | `fg/sub-700` | #48484A | #C7C7CC | | Placeholder, meta, dots | `text/soft-500`, `fg/soft-500` | #8E8E93 | #AEAEB2 | | Dormant and disabled glyphs | `fg/disabled-400` | #AEAEB2 | #8E8E93 | | Send and Stop disc | `brand/base` | #155DFC | #2B7FFF | | Glyph on that disc | `text/on-color/strong` | #FFFFFF | #FFFFFF | | Error panel | `state/error/lighter-50` | #FEF2F2 | #FB2C36 at 16% | | Error icon and Retry label | `state/error/base-500` | #FB2C36 | #FB2C36 | | Error reason | `state/error/dark-950` | #460809 | #FFA2A2 | | Retry fill | `colors/alpha/red/alpha-10` | #FB2C36 at 10% | #FB2C36 at 10% | | Composer shadow | `dropShadow/sm` | effect | effect | In dark mode bg/white-0 becomes #0E0E0F and text/strong-950 becomes #FFFFFF, so surface and copy swap ends of the ramp together. The error tint is the one that does not simply invert: #FEF2F2 becomes red at 16 percent alpha, and the reason text moves from the darkest red to a light one so it stays readable. ## How does the Prompt composer differ from the Input Composer? The Prompt composer is a multi-line shell with a tools row, a send or stop disc and an optional attachment. The Input Composer is a single 40 high bar with a field, an optional avatar and a send circle. The Input Composer, on the [Input](https://www.appetiteui.com/docs/input#composer) page, is for messages and comments. The field, the avatar and the send circle share one 40 pt height, in a Default or an Overlay style, with Empty and Typing states. Use the Prompt composer where the person writes a longer instruction to a model, needs tools, attaches a file, or must be able to stop a running answer. Neither contains the other. ## How do the AI components differ on iOS and Material 3? Message and Prompt composer have no iOS or Material 3 counterpart, because neither platform ships a conversation or a prompt component. Build them from this set. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Message | None | None | The platforms leave conversation rows to the app. Assistant text runs the full 361 with no bubble. | | Prompt composer | The nearest is iOS Text Field | The nearest is M3 Text Field | The native fields draw one field and nothing else. The composer adds the tools row, send and stop, and the attachment row. | The send, stop and tools discs are 32, under the minimum touch target of 44 pt on iOS and 48 dp on Android set by `platform/min-touch-target`, so extend their hit area in code. See [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge), [iOS](https://www.appetiteui.com/docs/ios) and [Material 3](https://www.appetiteui.com/docs/material-3). ## How should a conversation be laid out? Run the assistant as plain text on the full 361, keep Generating reachable, and announce what arrives. - Do: Let the assistant run as plain text on the full 361. The reader scans one column and a long answer is not squeezed into a 280 bubble. - Avoid: Do not give the assistant a bubble as well. Two bubbles read as two people, and the answer loses the width it was built for. Keep Generating reachable, because Stop is the only control on either component that ends a running answer. The set carries no Streaming and no Error on the User side, so handle a failed send on the composer or as a Toast. Announce what arrives. Put a streaming answer in a polite live region, move focus to Retry after an error, and give the send and stop disc one accessible name that changes with the state, Send then Stop. --- --- title: Alert description: An alert stops the flow to say what happened and offers the way out. Appetite UI Figma component: four types, Empty State, tokens and platform notes. group: Components source: https://www.appetiteui.com/docs/alert dateModified: 2026-10-03 --- # Alert Updated: October 3, 2026. Alert is a dialog that stops the flow to say what happened and, when it matters, what to do about it. ## Preview A centered dialog that holds the screen until it is answered. Pair it with an overlay, and dismiss the specimen from either button or the scrim. Specimen: Alert, Type Error. 340 x 268, padding 24 16 16, gap 24, radius 24. The card is 268 tall by arithmetic: 24 of top padding, a 152 top block, 24, a 52 button block, 16. The top block holds the file's sample copy, a title over a two line message. The card hugs, so a longer message grows it and leaves the padding and the gap alone. It enters at 200 on the emphasized curve, or on the default spring at response .40 and damping .80, the motion/dialog/enter tokens in the Motion collection. Source: the Alert page of the Appetite UI Figma file, read on October 2, 2026. ## Which types does Alert have? Alert has four types on one axis. The status takes the type's base-500 and its own icon, and the right hand action goes red on Error and stays brand on the other three. Specimen: Type Error, Success, Warning, Verified, in that order. 48 disc in a 56 halo, 28 icon, stroke 2.25. Success, Warning and Verified send you forward in brand blue, and only Error colors its own action. Verified is the default Type. Error, Success and Warning draw their status as a disc in a halo. Verified draws an eight point seal in the same 64 box, a white seal carrying the halo under a state/verified/base-500 seal, with the same check on top. ## What is Empty State for? A centered placeholder for a list or a screen with nothing to show: a status icon, a title, a short body and up to two buttons. It ships in three Types and has no card around it. Specimen: Empty State, Type Info, Error, Success. 345 wide, 340 and 316 tall, icon 80, gap 24. Use Empty State where a list, a search or a screen has no content yet or failed to load. Say what is missing in one line and give one action that fixes it. Info takes any icon through Icon Swap, and its default is wallet-minimal. Error and Success reuse the alert status at 80, a red x and a green check. Show secondary turns the second button off. Success is 316 tall where Info and Error are 340, because its body is one line of 24 where theirs is two of 48. Empty State ships 3 variants, one per Type. Source: the Empty State set of the Appetite UI Figma file, read on October 2, 2026. ## Properties Alert has one variant axis and two text properties, no boolean, no slot, no size. Empty State has one axis, two text properties, a boolean and an instance swap. | Property | Type | Default | | --- | --- | --- | | `Type` | Variant: Verified \| Error \| Success \| Warning | Verified | | `Message` | Text | Title of alert | | `Alert Text` | Text | A short line that explains what happened and what to do next. | | Property | Type | Default | | --- | --- | --- | | `Type` | Variant: Info \| Error \| Success | Info | | `Title` | Text | No transactions yet | | `Body` | Text | Your activity will appear here once you make your first payment. | | `Show secondary` | Boolean | true | | `Icon Swap` | Instance swap, Info only | wallet-minimal | Alert ships 4 variants, one per type. The two actions are Button instances at Size md Style Link, so their type, size and state live on Button. The left label is Dismiss on Neutral and the right label is Install on all four; only its color changes with the type. Empty State's two buttons are Brand Filled lg and Brand Weak lg, 56 tall and the full 345. ## Tokens Every value the component reads, resolved through its aliases to the primitive underneath. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/white-0` | #FFFFFF | #0E0E0F | Card fill, and the halo and ring behind the disc or the Verified seal | | `border/soft-100` | #E9E9EA | #2F2F31 | The 1px inside edge and the divider | | `text/strong-950` | #0E0E0F | #FFFFFF | Title | | `text/sub-700` | #48484A | #C7C7CC | Body and the Dismiss label | | `state/error/base-500` | #FB2C36 | #FB2C36 | The disc, and the right action on Error only | | `brand/base` | #155DFC | #2B7FFF | The right action on the other three, and the Info glyph | | `static/static-white-0` | #FFFFFF | #FFFFFF | The icon inside the disc | | `state/information/lighter-50` | #EFF6FF | #2B7FFF at 16% | The Empty State Info disc | Success is `#22C55E` then `#16A34A`, Warning `#FF6900` then `#F54900`, Verified `#47C2FF` then `#35ADE9`. Radius is `dimensions/radius/2xl` at 24 on the card and `full` on the disc and both buttons. The Alert card sits under the effect style `dropShadow/2xl` and the status halo under `dropShadow/xs`. The Empty State icons carry the same xs shadow. ## How does Alert differ on iOS and Material 3? Both platforms have a dialog of their own in the file: iOS / Alert in Liquid Glass and M3 / Basic dialog. Appetite UI Alert is one 340 wide card for both, and it adds status types that neither native dialog has. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Alert | iOS / Alert: Button Layout Stacked (300 by 443) or Side-by-Side (300 by 327), optional text fields. Regular Liquid Glass. | M3 / Basic dialog: 304 wide, 240 or 280 tall, radius 24, optional icon and divider. M3 / List dialog and Scrollable list dialog for choices. | Appetite UI has four status Types with a disc and always two Link buttons. iOS stacks three actions and holds text fields. The Platform collection gives dialogs a corner of 12 on iOS and 28 on Android (platform/dialog/corner), where Appetite UI is 24 on both. | | Empty State | None. | None. | Neither platform ships a placeholder for an empty list, so Appetite UI draws it: 345 wide, three Types, two buttons. | The two buttons are 44 high, which meets the minimum touch target of 44 pt on iOS and sits 4 under the 48 dp of Android, both from `platform/min-touch-target` in the Platform collection. The Empty State buttons are 56 high. ## When should I use an Alert? Interrupt the flow only when something needs acknowledgment: an error that blocks progress, or a confirmation before a destructive action. - Do: Dismiss on the left, the action on the right. Both are Link buttons, so neither shouts, and the color on the right is the only thing that says which way is forward. - Avoid: Do not swap them. The way out sits on the left in every alert, so the same thumb movement never means two different things. If the message can be delivered inline, deliver it inline. Use a Toast for something that passes on its own and a Modal for something that asks a question. --- --- title: Avatar description: Avatar shows a person or entity as a photo, initials or a symbol. Appetite UI Figma component: nine sizes, six hues, status badges and a group. group: Components source: https://www.appetiteui.com/docs/avatar dateModified: 2026-10-03 --- # Avatar Updated: October 3, 2026. Avatar shows a person or an entity as a photo, initials or a symbol, with an optional status badge in a corner. ## Preview A user or an entity, always circular, here as Type Photo at 6xl with a presence dot. The set ships twelve named portraits. Specimen: Avatar, Type Photo, Size 6xl. 80 px, radius full, badge 32. The disc behind initials and the symbol takes a hue from the person's name, the bottom badge has ten types, and Avatar group is a set of its own. Each has a section below. Source: the Avatar page of the Appetite UI Figma file, read on October 2, 2026. ## Which sizes does Avatar come in? Avatar has nine sizes, from 20 to 80, and the disc is the only thing the axis sets. The acronym ramp follows it, and so does the badge box, which is why the two smallest sizes have almost no room left for one. Specimen: 6xl, 5xl, 4xl, 3xl, 2xl, xl, lg, base, sm. 80, 72, 64, 56, 48, 40, 32, 24, 20. The badge box per size is 32, 28, 28, 24, 20, 18, 16, 12 and 12. At base and sm the box is 12, half the disc or more, so leave the badge off there. Two initials run down to xl, at 16/24. From lg the file prints one, 14 over a 32 disc and 12 at base and sm. ## Which types does Avatar have? Avatar has three ways to fill the disc: Photo takes an image, and Symbol and Acronym are the fallbacks. Both fallbacks sit on a pale disc, so a list of users keeps its rhythm when one of them has no picture. Specimen: Type Photo, Symbol, Acronym. shown at 4xl, 64 px. The symbol is two white ellipses clipped by the disc: a head at 40 percent of the disc and a body 80 by 60 percent, which scale with the circle. The photo is cropped the same way, by percentage, so one rule serves all nine sizes. The disc follows the Avatar name, and the twelve names share six hues, two names each. Gray is Erik Holmberg and Matteo Ribeiro, blue Maren Lindqvist and Sora Tanaka, sky Kai Andersen and Idris Yılmaz, purple Priya Sharma and Inés Cardoso, red Noemi Varga and Amara Diallo, yellow Leila Okonkwo and Zora Petrović. The default name is Maren Lindqvist, so the default disc is blue with the initials ML. The disc is colors/hue/200 and the initials colors/hue/900, the same in light and dark. Specimen: Symbol and Acronym in six hues, at 4xl. disc colors//200, label colors//900, shown at 4xl. ## Which status badges can an Avatar show? Avatar has two independent status booleans, Top for an action or a verification and Bottom for presence or an activity. Both badges wear a ring in the surface color so they read against any photo. Specimen: Top Status: Verified, Add, Check, Delete. ring 87.5, fill 75, icon 37.5 percent of the box. Specimen: Bottom Status: Online, Offline, Busy, Away. ring 62.5, dot 37.5 percent of the box. Only Verified breaks the circle: it is an eight point seal, one rounded square over the same square turned 45 degrees. The top and presence badges carry dropShadow/xs, and the activity badges carry none. The presence row runs on the photo, where the ring keeps a green dot on a light shoulder readable. Presence is color alone, so say it in text as well, for example in the row label. Specimen: Bottom Status, activity: Comment, Mention, Assigned, Completed, Due, Add. ring 100, disc 84.4, icon 50 percent of the box. Bottom Status has ten types. Online, Offline, Busy and Away are presence dots, and Comment, Mention, Assigned, Completed, Due and Add are activity icons for inbox rows. An activity icon is white on a state color: information, feature, away, success, highlighted and brand. It fills its box, so it is larger than a presence dot on the same avatar. Add is for the person's own entry, such as the You avatar in a story row. ## How do I show several people at once? Use Avatar group, an overlapping stack for shared context: the people in a project, a chat or a booking. Cap it at five and then show the number. Specimen: Size xs, md and lg. xs 24 at overlap 4, md 32 at overlap 6, lg 40 at overlap 8. Avatar group is its own set with Size xs, md and lg. It stacks Photo avatars at base, lg and xl, overlapping them by 4, 6 and 8, each with dropShadow/xs and an outside stroke in border/white-0 of 1, 2 and 2 so the edge of the avatar in front stays clean. A circle of the same size in bg/soft-100 carries the count in text/soft-500, at a stroke of 1 in every size. The set draws twelve, ten and eight avatars before its +5, so hide the layers past the fifth to keep the cap. ## Properties Three variant axes make the Avatar set 324 variants wide, and two booleans switch the badges on. The status badges and the group are their own sets. | Property | Type | Default | | --- | --- | --- | | `Size` | 6xl \| 5xl \| 4xl \| 3xl \| 2xl \| xl \| lg \| base \| sm | 6xl | | `Type` | Photo \| Symbol \| Acronym | Photo | | `Avatar` | Maren Lindqvist \| Kai Andersen \| Erik Holmberg \| Zora Petrović \| Noemi Varga \| Sora Tanaka \| Priya Sharma \| Idris Yılmaz \| Amara Diallo \| Inés Cardoso \| Leila Okonkwo \| Matteo Ribeiro | Maren Lindqvist | | `Top Status` | Boolean | false | | `Bottom Status` | Boolean | false | | Set | Property | Options | Default | | --- | --- | --- | --- | | `_Avatar Status - Top` | Type | Verified \| Add \| Delete \| Check | Verified | | `_Avatar Status - Bottom` | Type | Online \| Offline \| Busy \| Away \| Comment \| Mention \| Assigned \| Completed \| Due \| Add | Online | | `Avatar group` | Size | xs \| lg \| md | lg | The status sets are internal building blocks of Avatar. Switch a badge on with the two booleans and change its type on the nested instance. ## Tokens Every value the component reads, resolved through its aliases to the primitive underneath. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `colors/gray/200` | #D1D1D6 | #D1D1D6 | Disc, Erik Holmberg and Matteo Ribeiro | | `colors/gray/900` | #242427 | #242427 | Initials, Erik Holmberg and Matteo Ribeiro | | `colors/blue/200` | #BEDBFF | #BEDBFF | Disc, Maren Lindqvist and Sora Tanaka | | `colors/blue/900` | #0D2673 | #0D2673 | Initials, Maren Lindqvist and Sora Tanaka | | `colors/sky/200` | #C0EAFF | #C0EAFF | Disc, Kai Andersen and Idris Yılmaz | | `colors/sky/900` | #18658B | #18658B | Initials, Kai Andersen and Idris Yılmaz | | `colors/purple/200` | #CAC0FF | #CAC0FF | Disc, Priya Sharma and Inés Cardoso | | `colors/purple/900` | #3D1D86 | #3D1D86 | Initials, Priya Sharma and Inés Cardoso | | `colors/red/200` | #FFC9C9 | #FFC9C9 | Disc, Noemi Varga and Amara Diallo | | `colors/red/900` | #82181A | #82181A | Initials, Noemi Varga and Amara Diallo | | `colors/yellow/200` | #FEE685 | #FEE685 | Disc, Leila Okonkwo and Zora Petrović | | `colors/yellow/900` | #7B3306 | #7B3306 | Initials, Leila Okonkwo and Zora Petrović | | `static/static-white-0` | #FFFFFF | #FFFFFF | Symbol glyph and top badge icons | | `text/on-color/strong` | #FFFFFF | #FFFFFF | Activity badge icons | | `bg/white-0` | #FFFFFF | #0E0E0F | The ring behind every badge | | `border/white-0` | #FFFFFF | #0E0E0F | The outside stroke of every circle in a group | | `bg/soft-100` | #E9E9EA | #48484A | Group overflow circle | | `text/soft-500` | #8E8E93 | #AEAEB2 | Group overflow count | | `state/success/base-500` | #22C55E | #16A34A | Online, Completed, and the Check badge | | `state/error/base-500` | #FB2C36 | #FB2C36 | Busy, and the Delete badge | | `state/away/base-500` | #FE9A00 | #E17100 | Away, Assigned | | `state/faded/base-500` | #8E8E93 | #636366 | Offline, and the top Add badge | | `state/verified/base-500` | #47C2FF | #35ADE9 | Verified | | `state/information/base-500` | #155DFC | #155DFC | Comment | | `state/feature/base-500` | #7D52F4 | #693EE0 | Mention | | `state/highlighted/base-500` | #FB4BA3 | #E9358F | Due | | `brand/base` | #155DFC | #2B7FFF | The bottom Add badge | The disc hues are primitives, so they hold the same two values in dark as in light, and everything else on the component switches. Radius is `dimensions/radius/full` on the disc and on every badge. ## How does Avatar differ on iOS and Material 3? Neither platform ships an avatar component. Appetite UI Avatar is one circle in nine sizes with six fallback hues, status badges at the top and bottom and a stack, and the file draws no iOS or Material 3 counterpart. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Avatar | None. iOS draws contact photos inside its own list rows. | None. Material 3 list items accept a leading avatar in code, the kit draws none. | Appetite UI sets the disc from 20 to 80, falls back to initials or a symbol on a hue taken from the name, and adds up to two badges. The [List](https://www.appetiteui.com/docs/list) component takes a Leading Avatar at xl and base, and [Chip](https://www.appetiteui.com/docs/chip) has an Avatar type. | | Avatar group | None | None | A stack of up to five with a count, in three sizes, with an outside stroke so overlaps stay clean. | An avatar that opens a profile is a tap target, and at sm (20) and base (24) it is far under the minimum of 44 pt on iOS and 48 dp on Android, the value of `platform/min-touch-target` in the Platform collection. Extend the hit area, not the picture. ## How should I use status badges? Use one badge at a time, presence at the bottom and an action or a mark at the top. - Do: One badge at a time, and give it the corner that fits its job. Presence belongs at the bottom, an action or a mark belongs at the top. - Avoid: Do not hang badges on the small sizes. At 20 the badge box is 12, more than half the disc, and two of them leave nothing of the avatar to read. Give a photo avatar the person's name as its text alternative, and leave the alternative empty when the name is printed right beside it. A badge that is only a color, such as Online or Busy, needs the same words somewhere in text. --- --- title: Badge description: Badge is a small marker for a count, a status word or presence. Appetite UI Figma component: Pill, Circle and Dot, ten states, Overlay, tokens. group: Components source: https://www.appetiteui.com/docs/badge dateModified: 2026-10-03 --- # Badge Updated: October 3, 2026. Badge is a small marker for a count, a status word or presence, attached to the thing it describes. ## Preview A compact marker that attaches to something else. Pill carries a label, Circle a count, Dot presence. Specimen: Badge, Type Pill, Circle and Dot. 34 x 24, 20 x 20, 6 x 6, radius full. Pill is 24 high with a Semi Bold label, and a Dot property puts a 6 point leading dot in front of the label, which turns the Pill into a status word. A Color badge carries the dropShadow/xs effect and a Soft badge carries none. Source: the Badge page of the Appetite UI Figma file, read on October 2, 2026. ## Which types does Badge have? Badge has three types, all at radius full. Pill hugs its label, Circle is pinned square at 20 and Dot drops the label for a 6 mark. Specimen: Pill, then Circle, then Dot, a row each. 34 x 24, 20 x 20, 6 x 6, label 12/16 Semi Bold at padding 4 and 10. Pill is 24 high with padding 4 and 10 and a gap of 6, so its width is the label plus 20: 34 for a two digit count. Dot is 6 by 6 and has no text. Circle is a 20 by 20 box at padding 2 and holds two digits without clipping. A third digit does not fit, so above 99 switch to a Pill and print 99+. The label is Inter Semi Bold 12 on a 16 line at 0.1 tracking, the text style xs/emphasized. ## Which states does Badge have? Badge has ten states, each mapped to a token family, with Neutral on the faded family. Color fills with base-500 under a white label, and Soft fills with lighter-50, an alpha tint in dark, under a dark-950 label. Specimen: Neutral, Information, Error, Warning, Away, Success, Feature, Verified, Highlighted, Stable. Color, Soft and Dot in every cell. Cells read in the order named above, five to a row, each with a Color pill, a Soft pill and a Dot. Neutral reads the faded family: a Neutral Color pill is state/faded/base-500, and a Neutral Soft pill is state/faded/lighter-50 under a state/faded/dark-950 label. The Neutral Dot leaves the family, bg/strong-950 in Color and bg/soft-100 in Soft. Every other family paints Type Dot in Soft with light-200, because lighter-50 disappears at 6. In dark, lighter-50 and light-200 are alpha tints of the hue at 16 and 24 percent, so a Soft badge sits translucent over whatever it is pinned to. ## How do I show a status with Badge? Use Type Pill and switch Dot on: the dot carries the state color and the label says the word. Soft is the quiet version, Color the loud one. Specimen: Pill with Dot on, Soft and Color. Pill, Soft, Dot on, height 24. A Pill with Dot shows a status word, a Pill or Circle without it shows a count, and Dot alone marks presence. The Label property takes the word, and the pill hugs it. Keep the word to one or two. ## What is Overlay for? A label for photography: a place, a duration, a photo count. Overlay carries information, never a status. Specimen: Badge / Overlay, Size sm and md, Icon off and on. 28 and 36 tall, scrim at 42 percent, blur 16. Overlay is its own set, Badge / Overlay, with Size sm and md, an Icon variant, a Label property and a Trailing boolean for a chevron. Sm is 28 high at padding 6 and 10 with icons at 14, md is 36 high at padding 8 and 14 with icons at 16. The fill is bg/scrim as a paint at 42 percent over a 16 background blur (backdropBlur/md), with a 1 point glass/border stroke. The label and both icons are static white in light and dark, so the badge reads on any photo. ## Properties Three variant axes and two properties on the Badge set. The Overlay set has its own two axes and three properties. | Property | Type | Default | | --- | --- | --- | | `State` | Neutral \| Information \| Error \| Warning \| Away \| Success \| Feature \| Verified \| Highlighted \| Stable | Neutral | | `Type` | Pill \| Circle \| Dot | Pill | | `Style` | Soft \| Color | Soft | | `Label` | Text, Pill and Circle only | 12 | | `Dot` | Boolean, Pill only | false | | Property | Type | Default | | --- | --- | --- | | `Size` | sm \| md | sm | | `Icon` | True \| False | False | | `Label` | Text | Label | | `Icon Swap` | Instance swap | clock | | `Trailing` | Boolean | false | | `Trailing Swap` | Instance swap | chevron-down | A Dot type has no text node, so the Label does nothing there. Badge ships 60 variants: 10 states by 3 types by 2 styles, with no holes. Overlay adds four more on its own set. ## Tokens Each state reads its roles from its own family, and Success stands in for the other eight. Neutral and Overlay follow below. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `state/success/base-500` | #22C55E | #16A34A | Color fill, and the Soft leading dot | | `text/on-color/strong` | #FFFFFF | #FFFFFF | Color label and leading dot | | `state/success/lighter-50` | #F0FDF4 | #22C55E at 16% | Soft fill of Pill and Circle | | `state/success/dark-950` | #09361B | #86EFAC | Soft label | | `state/success/light-200` | #BBF7D0 | #22C55E at 24% | Soft fill of Type Dot | | `state/faded/base-500` | #8E8E93 | #636366 | Neutral Color fill | | `state/faded/lighter-50` | #F4F5F5 | #6A7282 at 16% | Neutral Soft fill | | `state/faded/dark-950` | #0E0E0F | #C7C7CC | Neutral Soft label | | `bg/strong-950` | #0E0E0F | #FFFFFF | Neutral Type Dot in Color | | `bg/soft-100` | #E9E9EA | #48484A | Neutral Type Dot in Soft | | `bg/scrim` | #000000 at 40% | #000000 at 48% | Overlay fill, as a paint at 42% | | `glass/border` | #FFFFFF at 50% | #FFFFFF at 12% | Overlay stroke | | `static/static-white-0` | #FFFFFF | #FFFFFF | Overlay label and icons | Radius is `dimensions/radius/full` on every type, and the Color style adds the `dropShadow/xs` effect style. Swap success for any of the other eight families and the roles hold. ## How does Badge differ on iOS and Material 3? Both platforms draw a badge as a count on a tab item or an icon. Appetite UI Badge adds a status pill with a dot and an Overlay for photos, and the file draws no iOS or Material 3 Badge to compare. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Badge, Circle and Pill | The badge on a tab item or a list row, set with the SwiftUI `badge` modifier or the UIKit `badgeValue` of a tab item | The Material 3 Badge, a small dot or a large badge with a number | Appetite UI draws a Circle at 20 by 20 and a Pill at 24 high on every platform. | | Badge, Pill with Dot | None. iOS has no status pill. | None. Material 3 marks status with a Chip or text. | Appetite UI adds a 6 point leading dot and a Soft style so a status word reads without a filled block. | | Badge / Overlay | None | None | A scrim label for photography. Neither platform names one. | A badge is not a control, so it has no touch target of its own. The control it sits on keeps the minimum of 44 pt on iOS and 48 dp on Material 3, set by `platform/min-touch-target` in the Platform collection. ## Which Badge type should I use? Use a dot for presence, a circle for a count and a pill with a dot for a status word. - Do: Pick the type by what you have to say. A dot means something is there, a circle how many, a pill with a dot what it is. - Avoid: Do not run a sentence through a badge, or stack three of them. At 24 high it marks something else and is not a label of its own. Pin a badge to the thing it describes. If what you have to say is a sentence, use a [Chip](https://www.appetiteui.com/docs/chip) or an [Alert](https://www.appetiteui.com/docs/alert). Never let color carry the meaning alone: the label or the control name must say it too. For text at 12, prefer Soft. White on a Color fill reaches 4.5 to 1 only for Information (5.3) and Feature (4.8) in light, while every Soft pair measures at least 8.6 in light and 6.8 in dark. Contrast computed on October 2, 2026 from the resolved token values, with a Soft tint taken over bg/white-0. --- --- title: Breadcrumb description: Breadcrumb shows where a screen sits in a hierarchy and takes people back up it, from two to five levels. Appetite UI component for Figma, rare on mobile. group: Components source: https://www.appetiteui.com/docs/breadcrumb dateModified: 2026-10-03 --- # Breadcrumb Updated: October 3, 2026. Breadcrumb shows where the current screen sits in a hierarchy, and takes people back up it. It earns its place only in a drill-down deeper than Back can explain. ## Preview A hierarchy trail of three levels, the last one active. Rare on mobile: use it only when a drill-down runs deeper than Back can explain. Specimen: Breadcrumb, Quantity 3. 388 x 20, gap 8, item gap 6. The last item is the page you are on, so it takes the strong tokens and stops being a link. Everything before it stays sub. ## How many levels can a Breadcrumb have? Two to five levels. The track hugs, stays 20 tall and adds 140 for every level past the first: eight of gap, the sixteen wide chevron, eight again, then the 108 item. Specimen: Quantity 2, 3, 4, 5, top to bottom. 248, 388, 528, 668 wide, 20 tall. Five levels measure 668, which does not fit a 390 screen or this column. The track scrolls in place instead of wrapping, because a breadcrumb on two lines stops reading as one line of descent. ## What is a Breadcrumb item? The building block behind every level. One state axis and two booleans, so a level can be an icon and a label, a label alone, or an icon alone. Specimen: State Default, State Active, text only, icon only. 108 x 20, gap 6, icon 20 box on a 15 vector. Default paints `fg/sub-700` and `text/sub-700`, Active paints `fg/strong-950` and `text/strong-950`, so icon and label always carry the same value. The chevron stays `fg/soft-500` at every level. Text false is the usual first level. ## How does Breadcrumb differ on iOS and Material 3? Neither platform has a breadcrumb. iOS puts the previous screen's title on the back button, and Material 3 uses the up arrow in the top app bar and the system back gesture. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Breadcrumb, Quantity 2 to 5, item 108 x 20 | No counterpart, the back button carries the previous title | No counterpart, the top app bar has an up arrow | Appetite UI shows the whole path at once. The platforms show one step back and leave the rest to the back gesture | Each level is 20 tall, well under the 44 minimum touch target on iOS and the 48 on Android from `platform/min-touch-target`. Keep the drawn item at 20 and extend its hit area to 44 or 48 in code. In HTML, wrap the trail in a nav named Breadcrumb and mark the last level with aria-current set to page. See [Top Bars](https://www.appetiteui.com/docs/top-bars) for the back button the platforms use instead. ## Properties One axis on the published component. The rest sit on the item inside it, a building block not meant for direct use. | Property | Type | Default | | --- | --- | --- | | `Quantity` | 2 \| 3 \| 4 \| 5 | 2 | | `State` | Default \| Active, on the item | Default | | `Icon` | Boolean, on the item | true | | `Text` | Boolean, on the item | true | | `Edit Text` | Text, on the item | Breadcrumb | Breadcrumb ships 4 variants, one per quantity. The item ships 2, one per state, and is composed into all four, so a change there reaches every level of every trail. ## Tokens Three values and nothing else. No fill, no border, no radius anywhere in the component. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `text/sub-700` | #48484A | #C7C7CC | Every level that is not the current one, label and icon | | `text/strong-950` | #0E0E0F | #FFFFFF | The active level, label and icon | | `fg/soft-500` | #8E8E93 | #AEAEB2 | The chevron between levels | The icon tokens, `fg/sub-700` and `fg/strong-950`, resolve to the same primitive as their text counterpart in both modes. On white, the sub text measures 9.1 to 1 and the active text 19.3 to 1. The chevron, `fg/soft-500`, measures 3.26 to 1, above the 3 to 1 asked of a graphic. It carries no meaning of its own, because the level labels and the current page mark already do. ## Guidelines - Do: Save it for a drill-down deep enough that Back stops answering the question. Drop the label on the root and let the icon carry it. - Avoid: Two levels do not need a trail. One step back is a Back button, and a breadcrumb there spends a whole row saying what the header already said. A breadcrumb on mobile is worth it only for deep drill-downs. Anywhere else, the back button and the screen title already do the job. --- --- title: Button description: Button performs an action, and its style shows which one matters most. Appetite UI Figma component: 4 styles, five states, tokens and platform notes. group: Components source: https://www.appetiteui.com/docs/button dateModified: 2026-10-03 --- # Button Updated: October 3, 2026. Button performs an action. Its weight tells people which action on the screen matters most. ## Preview Brand, filled, large. The icon slots hold the component's default circle placeholder. Specimen: Type Brand, Style Filled, Size lg. 56 px, radius full. ## Type and style Type carries the meaning and Style carries the weight. The two axes give twelve combinations on the same geometry. Specimen: Type Brand, Neutral, Error by Style Filled, Outline, Weak, Link. Size md. ## How tall is a Button? Button is 36, 44 or 56 high (sm, md, lg), and all three clear the 44 pt target once the tap area is applied. The heights are fixed so buttons line up with fields and list rows on the same screen. Specimen: Size. 36 / 44 / 56 px. ## Which states does Button have? Button has five states: Default, Pressed, Focused, Loading and Disabled, on every combination of type and style. A finger does not hover, so the set has no Hover state; with a pointer, a hover moves a specimen toward its Pressed fill. Specimen: State by Style at Type Brand, Size md. Brand, Filled, md, in Default / Pressed / Focused / Loading / Disabled. Specimen: Neutral, Pressed and Focused, and Error, Focused. Size md, four styles in each row. Focused is the focusRing/brand effect style, a 2 pt gap in the surface color and then a 2 pt ring in brand/base; Type Error uses focusRing/error. The ring sits on the button shape, and a Link button also takes its pressed fill under the ring. Loading keeps the container of Default and swaps the label for a ring spinner. The spinner is a 24 box with a 20 ring of 2 pt and an arc of about 109 degrees that turns once every 1.2 seconds. Pressed keeps each style recognizable: Outline fills with brand/alpha-10 and keeps its stroke, Weak deepens to brand/alpha-16, Link gets brand/alpha-10, and Filled steps to brand/pressed. Disabled paints Filled and Weak bg/soft-100, leaves Outline white inside a border/soft-100 line, and gives Link no fill. The other button components on the page carry their own states, described with each one below. The white label measures 3.76 to 1 on Brand Filled in Dark and 3.81 to 1 on Error Filled in both modes, under the 4.5 to 1 asked of text at this size. Error Filled Pressed takes state/error/dark-700, which turns light in Dark, and its label falls to 1.92 to 1 there. A real button keeps the 2 plus 2 focus ring for keyboard focus, and size sm still needs a 44 pt hit area in code. 360 variants: Type by Style by Size by State by Icon Only, no holes. Read from Button 53:4429 of the Figma file on October 2, 2026. ## Icon only Set Icon Only to True and the label wrapper is dropped. The button becomes a circle at the same height. Specimen: Icon Only, True. 36 / 44 / 56 px. ## Properties The Figma component properties, named exactly as the right hand panel names them. | Property | Type | Default | | --- | --- | --- | | `Type` | Brand \| Neutral \| Error | Brand | | `Style` | Filled \| Outline \| Weak \| Link | Filled | | `Size` | sm \| md \| lg | sm | | `State` | Default \| Pressed \| Loading \| Disabled \| Focused | Default | | `Icon Only` | True \| False | False | | `Icon Left` | Boolean | true | | `Icon Right` | Boolean | true | | `Icon Left Swap` | Instance swap | circle | | `Icon Right Swap` | Instance swap | circle | | `Icon Swap` | Instance swap, used when Icon Only is True | circle | | `Text` | Text | Button | ## Tokens Every value the component reads, resolved through its aliases to the primitive underneath. Change one and it changes in Figma, the CSS, and all three native outputs. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `brand/base` | #155DFC | #2B7FFF | Brand filled fill, Brand outline stroke, Brand quiet labels, focus ring | | `brand/pressed` | #193CB8 | #155DFC | Brand filled pressed | | `brand/alpha-10` | #2B7FFF at 10% | #2B7FFF at 10% | Brand weak fill, Brand outline and link pressed | | `brand/alpha-16` | #2B7FFF at 16% | #2B7FFF at 16% | Brand weak pressed | | `static/static-white-0` | #FFFFFF | #FFFFFF | Label on Brand and Error filled | | `static/static-facebook-blue` | #1877F2 | #1877F2 | Social Button, Facebook Filled fill | | `static/static-facebook-blue-pressed` | #106BE1 | #106BE1 | Social Button, Facebook Filled fill while pressed | | `bg/white-0` | #FFFFFF | #0E0E0F | Outline fill, and the gap in the focus ring | | `bg/strong-950` | #0E0E0F | #FFFFFF | Neutral filled fill | | `text/white-0` | #FFFFFF | #0E0E0F | Label on Neutral filled | | `bg/surface-800` | #2F2F31 | #D1D1D6 | Neutral filled pressed | | `bg/weak-50` | #F4F5F5 | #242427 | Neutral weak fill, Neutral outline and link pressed | | `bg/soft-100` | #E9E9EA | #48484A | Neutral weak pressed, disabled fill | | `border/soft-100` | #E9E9EA | #2F2F31 | Neutral outline stroke, disabled outline stroke | | `text/sub-700` | #48484A | #C7C7CC | Neutral outline, weak and link label | | `text/strong-950` | #0E0E0F | #FFFFFF | Neutral label while pressed or loading | | `state/error/base-500` | #FB2C36 | #FB2C36 | Error filled fill, Error stroke and label, error ring | | `state/error/dark-700` | #C10007 | #FFA2A2 | Error filled pressed | | `colors/alpha/red/alpha-10` | #FB2C36 at 10% | #FB2C36 at 10% | Error weak fill, Error outline and link pressed | | `colors/alpha/red/alpha-16` | #FB2C36 at 16% | #FB2C36 at 16% | Error weak pressed | | `text/disabled-400` | #AEAEB2 | #8E8E93 | Disabled label | | `dimensions/radius/full` | 9999 | 9999 | Corner radius, every size | brand/pressed is a semantic alias, so the Pressed fill moves with the brand: colors/blue/700 in Light and colors/blue/500 in Dark, two steps darker than brand/base in Light and one in Dark. static/static-white-0 is white in both modes, so a label on a brand fill stays white on a dark screen. The focus ring is the focusRing/brand and focusRing/error effect styles: two drop shadows at blur 0, spread 2 in bg/white-0 and spread 4 in brand/base or state/error/base-500. ## How does Button differ on iOS and Material 3? Appetite UI Button is one component for both platforms: a capsule at three heights with Filled, Outline, Weak and Link styles. iOS and Material 3 each have their own button sets in the file, with their own sizes and styles. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Button | iOS / Button: Size Small, Medium and Large by Style Borderless, Bordered and Bordered - Prominent, with Destructive and Icon Only. Liquid Glass Text and Symbol sets add Glass and Glass Prominent. | M3 / Button in five sets (filled, tonal, outline, elevated, text), each Type Round or Square by Size XSmall to XLarge by State Enabled, Hovered, Focused, Pressed, Disabled | The iOS set starts at 28 high where Appetite UI sm is 36. Material 3 has five sizes and a real Hovered state. Appetite UI has three sizes, an Error type and a Loading state that neither native set draws. | | Compact Button | iOS / Button - Liquid Glass - Symbol, a 50 circle | M3 / Icon Button, 40 by 40, Standard, Filled, Tonal and Outlined | Appetite UI is a 32 circle with three shells. | | Floating Action Button | None. On iOS use a toolbar action. | M3 / FAB and M3 / Extended FAB | Appetite UI draws one 56 circle with an Open stack. Material 3 FAB comes in 40, 56 and 96. | | Social Button | None | None | Neither platform ships a sign-in button; the brand rules of each provider apply. | The minimum touch target is 44 pt on iOS and 48 dp on Material 3, set by `platform/min-touch-target` in the Platform collection. Size sm is 36 high, so give it a 44 pt hit area on iOS and 48 dp on Android in code. ## When should I use a filled Button? Use one filled Button per screen, for the action that matters most, and pair it with a link for the way out. - Do: One filled button per screen. Pair it with a link so the destination of the eye is never in doubt. - Avoid: Reserve Error for destructive actions. A filled Error on the safe choice makes two filled buttons, so the safe path and the risky one are equally loud. The same Figma page ships five more button components, documented below: Quick Action Button, Social Button at 128 variants, Compact Button, Button / Overlay and the Floating Action Button. ## Quick Action Button A circle icon with a label under it, in five semantic colors and three states, for shortcut grids and the action row on a wallet or banking screen. Use Button for the main action of a screen. Specimen: Type Brand, Neutral, Success, Warning, Error. 56 x 78, circle 56 at radius 24, icon 22, label 12/16. Specimen: State Default, Pressed, Disabled, on Type Brand. brand/lighter, brand/light, bg/weak-50. Type moves the container fill and the icon together and leaves the label on text/strong-950 in all five. Pressed steps each tint up one stop, lighter to light, and leaves the icon color alone. Disabled flattens the axis: every color lands on bg/weak-50 with the icon in fg/disabled-400 and the label in text/disabled-400. The five colors are the only thing an instance cannot override, because icon and label are both properties. ## Social Button Third-party sign-in for four providers, at one fixed height, so the stack under a login form stays even whichever set you ship. Never recolor the brand marks. Specimen: Company Google, Facebook, Apple, X at Style Filled. 135 x 56, radius full, padding 0 and 16, gap 8, label 16/24 Semi Bold. Specimen: Style Filled, Outline, Weak, Link at Company Google. bg/strong-950, bg/white-0 with a 1px border, bg/weak-50, no fill. Style changes the shell and the mark stays put. Google keeps its four colors in every style, Facebook stays on its own blue until Filled paints the mark white, and Apple and X flip between fg/white-0 and fg/strong-950. Facebook Filled uses static/static-facebook-blue, and static/static-facebook-blue-pressed while pressed, so it holds the same value in both modes, and its label, mark and loading arc take static/static-white-0 for the same reason. Every style is 56 tall with 16 of padding, Link included. The label defaults to Continue, so name the provider on every real instance, for example Continue with Google. ## Compact Button An icon-only control at 32, for toolbars, image overlays and anywhere a full button would crowd the row. Three shells, four states. Specimen: Style Outline, Transparent, White at State Default. 32 square, radius full, icon 20 at stroke 1.75. Specimen: State Default, Pressed, Focused, Disabled, on Style Outline. bg/white-0, bg/soft-100, bg/white-0 under a 1 brand/base stroke and the ring, bg/weak-50. Pressed paints all three styles bg/soft-100, and Disabled paints Outline and White bg/weak-50 while Transparent stays clear. Only Outline has a border, border/soft-100 at 1 pt in Default, Pressed and Disabled. Focused keeps each style's own fill under a 1 pt brand/base stroke drawn outside the edge, then the focus ring. Transparent has no fill, so its ring follows the stroke alone. At 32 the circle is smaller than a finger, so give it a 44 pt hit area on iOS and 48 dp on Android in code. ## Button / Overlay A circular icon button for use on top of photography. A scrim and a background blur keep the glyph legible on any image, in both modes. Specimen: Size sm, md, lg at State Default, then State Pressed. 36 / 44 / 56 px circle, icon 18 / 20 / 24, bg/scrim at 42 percent, blur 16. The fill is bg/scrim at 42 percent, and 58 percent while pressed, over the backdropBlur/md style, a 16 background blur. The glyph is static/static-white-0 in both modes and swaps with Icon Swap. The set has State Default and Pressed only, with no Focused, Disabled or Loading. Give a live one the 2 plus 2 focus ring in code. ## Floating Action Button One screen-level primary action, pinned above the content, with an expanded stack behind it. It is Android-native, so on iOS use a toolbar action instead. Specimen: State Close. 56 square, radius full, brand/base, plus at 24, dropShadow/lg. Specimen: State Open. four actions, 16 from the button, 12 apart, label pill 40 tall at radius 12, 16 from its circle. Close is one 56 circle. Open turns that circle Neutral Weak with an x and hangs four expanded actions above it, each a 56 brand circle with its label to the left. Both main circles sit under dropShadow/lg. A label is a 40 tall pill at radius 12 in bg/strong-950 with text/white-0, so the pill and its text invert in Dark. The stack sits outside the component's own 56 by 56 frame, which does not clip, so an instance measures 56 and paints 201 by 332. State is the only property, so the four actions carry a placeholder circle and the words New post, Upload photo, Scan code and Message until you override each one. The set has no Focused state, so give a live one the 2 plus 2 focus ring in code. --- --- title: Card description: Card groups an image, a title and supporting lines into one tappable surface. Appetite UI Figma component: three types, two sizes, Pressed and tokens. group: Components source: https://www.appetiteui.com/docs/card dateModified: 2026-10-03 --- # Card Updated: October 3, 2026. Card groups an image, a title and a few supporting lines into one surface that opens a single thing. ## Preview Vertical Card, Size Default, State Default. An 8 frame runs around the image, and the image takes the card's radius less that frame, so the picture follows the corner of the card. Specimen: Vertical Card, Size Default. 340 wide, radius 24, frame 8, image radius 16. The card radius is 24 and the image radius 16, because an inner radius equals the outer radius minus the padding between them. The Vertical Card carries its rating on the title row. Source: the Vertical Card set of the Appetite UI Figma file, read on October 2, 2026. ## Which types does Card have? Card has three types, each its own set on one shell of stroke, radius and shadow. Vertical leads with the image, Horizontal turns it on its side for a list, Icon drops the image for a tile. Specimen: Vertical, Horizontal, Icon. same 340 shell, radius 24, content gap 4. The three are separate component sets, so an instance cannot be switched from Vertical to Horizontal. They share the property list and the corner Badge, a real Badge instance at State Success, Type Pill and Style Soft. They do not share the title size: Vertical and Icon run 24/32 at Default and Horizontal runs 20/28. Vertical Card, Horizontal Card and Icon Card hold 4 variants each: Size by State. ## What changes at Size Compact? Compact is its own layout. Vertical and Icon narrow to 240 and tighten their padding, Horizontal keeps 340 and shrinks its image, and every title and subtitle steps down. Specimen: Size Default, Size Compact. 340 / 240, content padding 12 / 8, title 24 / 18, subtitle 14 / 12. Compact restructures the Horizontal Card: Default stacks the rating above the meta line, Compact puts them on one row at gap 4. The image goes from 132 to 92, so the card drops from 148 to 108 high. On Icon Card, Size also moves the tile from 40 to 36 and the content padding from 16 to 12. Compact Vertical is 240 x 274 against 340 x 303, Compact Icon 240 x 160 against 340 x 180. ## Which states does Card have? Pressed swaps the fill to bg/weak-50 and clears the shadow, so the card reads as pushed into the page. The stroke stays, and the card does not move, scale or dim. Specimen: State Default, State Pressed. fill bg/white-0 then bg/weak-50, shadow off. Card has no Hover state. Add a pointer hover in code only where your product has a pointer. The Icon tile is bg/weak-50, the same as the pressed fill, so under Pressed it merges with the card. The Icon Card keeps its height under Pressed, 180 in both states. ## Which optional parts can a Card show? Four booleans turn on extra parts: Price on all three sets, Favorite and Dots on Vertical Card, and Status on Horizontal Card. All four ship off. Specimen: Price, Favorite, Dots, Status. Favorite 36 at radius 16, five dots of 6, Price 16 / 24, Status badge. Favorite is a 36 white square at radius 16 in the top right of the image, under dropShadow/sm. Dots mark the position in an image carousel, five at a time: the active one white, the other four white at 45 percent. Status is a Neutral Soft Badge at the end of the Horizontal column, so a small thumbnail does not need a badge over it. Price is a 16/24 Semi Bold line under the meta text. Favorite is 36 wide, below the minimum touch target. Give it a 44 pt hit area on iOS and 48 dp on Android in code. ## Properties Two variant axes and the same instance properties on all three sets. Image and Image Swap belong to Vertical and Horizontal, Icon to Icon Card, Favorite and Dots to Vertical, Status to Horizontal. | Property | Type | Default | Sets | | --- | --- | --- | --- | | `Size` | Default \| Compact | Default | All | | `State` | Default \| Pressed | Default | All | | `Image` | Boolean | true | Vertical, Horizontal | | `Image Swap` | Instance swap, _Card Image | _Card Image | Vertical, Horizontal | | `Icon` | Instance swap | circle | Icon | | `Subtitle` | Boolean | true | All | | `Rating` | Boolean | true | All | | `Description` | Boolean | true | All | | `Badge` | Boolean | true | All | | `Price` | Boolean | false | All | | `Favorite` | Boolean | false | Vertical | | `Dots` | Boolean | false | Vertical | | `Status` | Boolean | false | Horizontal | | `Title Text` | Text | Title | All | | `Subtitle Text` | Text | Subtitle | All | | `Description Text` | Text | Meta · Info | All | | `Rating Text` | Text | 4.8 · 128 | All | | `Price Text` | Text | $180 night | All | Every content row is a boolean, so a card with no rating loses the row and its height follows. Source: the three Card sets of the Appetite UI Figma file, read on October 2, 2026. ## Tokens Every value the card reads, resolved through its aliases to the primitive underneath. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/white-0` | #FFFFFF | #0E0E0F | The card fill | | `border/soft-100` | #E9E9EA | #2F2F31 | The 1 pt stroke, drawn outside | | `bg/weak-50` | #F4F5F5 | #242427 | Pressed fill and the Icon tile | | `bg/soft-100` | #E9E9EA | #48484A | The image slot | | `fg/disabled-400` | #AEAEB2 | #8E8E93 | The placeholder glyph in the image slot | | `text/strong-950` | #0E0E0F | #FFFFFF | Title and Price | | `text/sub-700` | #48484A | #C7C7CC | Subtitle and rating | | `text/soft-500` | #8E8E93 | #AEAEB2 | Meta line | | `brand/base` | #155DFC | #2B7FFF | The circle in the Icon tile | | `state/success/lighter-50` | #F0FDF4 | #22C55E at 16% | Corner badge fill | | `state/success/dark-950` | #09361B | #86EFAC | Corner badge label | | `colors/yellow/400` | #FFB900 | #FFB900 | The rating star, one mode | | `static/static-white-0` | #FFFFFF | #FFFFFF | Favorite fill and the first dot | | `static/static-white-alpha-45` | #FFFFFF at 45% | #FFFFFF at 45% | The four inactive dots | | `static/static-black-950` | #0E0E0F | #0E0E0F | The heart in Favorite, one value in both modes | Radius 24 is `dimensions/radius/2xl`, the image and Favorite 16 are `dimensions/radius/xl` and the Icon tile 12 is `dimensions/radius/lg`. The shadows are `dropShadow/xs` on the card and `dropShadow/sm` on Favorite, and Pressed clears the first. The rating star is a single mode primitive, so it holds #FFB900 on a dark card, as it does on the Rating component. The meta line is text/soft-500, 3.26 to 1 on white, so raise it in your own product if the line carries essential information. In code the whole card is one focusable control with a visible focus ring and a name that reads its title. ## How does Card differ on iOS and Material 3? Material 3 ships a Card with three styles, and the Apple Platform pages of the file have no card, only list and grouped cells. Appetite UI Card is one surface with one hairline and one shadow on both platforms. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Card | None. Apple groups content in list cells: iOS / List in Plain, Grouped and Inset Grouped. | M3 / Card in Elevated, Filled and Outlined, 328 x 200 at radius 12 | Appetite UI is 340 wide at radius 24 with one fill, a hairline and dropShadow/xs. Material 3 changes the surface per style, Elevated, Filled or Outlined, where Appetite UI keeps one surface and changes only its fill on Pressed. | The tap target is the whole card, at least 108 high, so it clears the minimum touch target of 44 pt on iOS and 48 dp on Material 3 set by `platform/min-touch-target`. ## Which Card set should I use? Use Vertical when the picture is the reason to tap, Horizontal when the list has to stay short, Icon when an image would carry no meaning. - Do: Switch off the rows you have no data for. Every content row is a boolean, so a card without a rating loses the row rather than printing an empty one. - Avoid: true --- --- title: Chart description: Which chart fits your data? 16 mobile chart types in Figma, plus Legend and Sparkline, on four series colors that follow light and dark. group: Components source: https://www.appetiteui.com/docs/chart dateModified: 2026-10-03 --- # Chart Updated: October 3, 2026. Chart is a set of mobile chart types, one for each common data shape. Every one is 361 wide so it fits a 393 point screen, and all of them are drawn on the same four series colors, so a chart answers one question at a glance. ## Preview Weekly revenue as a bar chart. One column is Solid and carries its value, the other six rest in Soft, and a dashed line marks the average. Specimen: Bar. 361 wide, bar 24, track 8 radius, average line dashed. Chart ships with 16 types, plus Legend and Sparkline. Every drawing on this page is a live SVG colored only by tokens, so switch the theme and it redraws in Dark. The charts and the Sparkline play their entrance from the Figma file once, as you scroll to them. ## Which chart should I use? Pick by the shape of the data. A trend over time takes Line, a comparison between categories takes a bar, a share of a whole takes Donut, one value inside a known range takes Gauge. | Chart | Data shape | Use it for | Rule | | --- | --- | --- | --- | | Line | Two series over ordered points | A trend and its comparison period | Smoothing never passes a data point. Scrub, tooltip and range are optional. | | Area | Parts of one total over time | Channels that share a total | Three bands on the brand ramp, the total as a line 2.5 wide. | | Candlestick | Open, high, low and close per day | A price over a month | Each candle opens on the previous close. A 7 day average and a dashed last price line. | | Bar | One series over categories | A weekly total with one column highlighted | No y axis. The value sits on the highlighted column. | | Bar - Grouped | Two series per category | This period against last | Two series at most. A third bar in a 41 wide column is 12 wide and unreadable. | | Bar - Stacked | Parts of each column total | How each column splits | Three segments at most. Past that the middle bands cannot be compared. | | Bar - Horizontal | Ranked categories with word names | Top sources, top pages | Use it when names are words, not dates. A word does not fit under a column. | | Waterfall | A start total, steps, an end total | A bridge such as monthly recurring revenue | Gains green, losses red, totals in chart/series-1. | | Donut | Parts of a whole | A split of one total | Four segments at most, largest first, from twelve o'clock clockwise. | | Ring | Progress against targets | Daily goals | Three rings at most. Each needs a legend row because an arc does not say what it counts. | | Gauge | One value in a known range | Storage, a credit score | Only with a real maximum. With no ceiling, show the number alone. | | Bullet | Actual against a target | Progress toward a target | Tone the bar by whether the target was met. | | Funnel | Steps of a conversion | Where people drop off | Four steps is the mobile limit. Show the drop between steps. | | Heatmap | Intensity by week and day | Activity and streaks | Five levels. Swap the level to change a cell. | | Scatter | Two values per point, two groups | A correlation | A dashed trend with its confidence band and one highlighted point. | | Radar | Six values on one scale | The profile of one subject | Six axes with rings at 25, 50, 75 and 100. | The rules are the ones each Figma component states in its own description. ## Line, Area and Candlestick Use these when the x axis is time. Line compares two periods, Area splits one total into channels, Candlestick shows the range of a price on each day. Specimen: Line. 361 by 386, this week 2.5 wide, last week dashed. Specimen: Area. 361 by 386, bands at alpha 72, 48, 24. Specimen: Candlestick. 361 by 292, wick 1, body 7. Line and Area curves are Catmull-Rom smoothing converted to cubic Beziers, so the curve bends between points and every point stays where the data put it. A curve that passes beside a data point misstates the data. Show Tooltip and Show Range are properties, and Range is a Segmented Control at Size Small with five tabs. ## Bar, Grouped, Stacked, Horizontal and Waterfall Use these to compare categories. Vertical bars suit days and months, Horizontal suits names, Waterfall suits a total that changes in steps. Specimen: Bar with Show Track. 361 by 292, bars 24 wide, 12 apart. Specimen: Bar - Grouped. 361 by 328, two bars of 19.64, 2 apart. Specimen: Bar - Stacked. 361 by 328, three segments, 2 apart. Specimen: Bar - Horizontal. 361 by 236, track 229 by 8. Specimen: Waterfall. 361 by 292, bars 32 wide. Show Track draws a Weak track behind every column and is off by default, which is how the Preview draws Bar. Bars are 24 wide in a 41 wide column, columns are 12 apart, and every column stands on a baseline 8 above its label. On Bar a column is as tall as the value divided by the maximum, times 136, plus 48. Grouped and Stacked show no values on the bars. ## Donut, Ring, Gauge, Bullet and Funnel Use these for a share, a progress or a position: Donut and Ring for parts of a whole, Gauge for one value in a range, Bullet for a target, Funnel for conversion. Specimen: Donut. 361 by 160, ring 160, band 20. Specimen: Ring. 361 by 240, rings 16 wide, 2 apart. Specimen: Gauge. 361 by 235, half circle 240, band 20. Specimen: Bullet. 361 by 294, track 10, tick 2 by 16. Specimen: Funnel. 361 by 364, bars 26 high, radius 8. Donut segments start at twelve o'clock and run clockwise, 2 degrees apart, so a reader always starts in the same place. Ring arcs have butt ends. The Gauge value ends in round caps made of circles 20 across. In Bullet the tick is the target and the bar is where you are. ## Heatmap, Scatter and Radar Use these to show a pattern: Heatmap for intensity by day, Scatter for two measures at once, Radar for the profile of one subject on six axes. Specimen: Heatmap. 361 by 312, cells 22, 3 apart. Specimen: Scatter. 361 by 300, dots 6 to 12. Specimen: Radar. 361 by 332, radius 96, rings at 100, 75, 50, 25. Heatmap fills the 361 with 13 weeks of 22 wide cells and 3 between them. Its five levels are tokens on the brand ramp, so a level changes the token and a hand set fill never appears. Scatter sizes its dots by group, 6 to 10 across for New and 8 to 12 for Returning, with a ring in the surface color so overlaps stay separate. ## What does every chart header carry? Every chart opens with the same header: a title, a value and, on the time charts, a trend chip with a comparison text. Show Header turns it off when the surrounding card already carries a title. Specimen: Header with context, then without. Title 14, Value 30, chip 68 by 24, gap 4. The header is 88 high with a context row and 60 without one. Ring, Gauge, Bullet, Heatmap, Scatter and Radar use the short header, and Donut has none. Label, Value, Show Context and Context are properties, so the title and the figure are text you edit. ## How many series does the palette carry? Four. chart/series-1 to chart/series-4 are the categorical colors, and chart/muted and chart/soft are the neutrals a chart pairs with them. Past four series, switch to a bar chart or group the rest as Other. Specimen: Series 1 to 4, muted and soft. series 1 to 4, then muted and soft. Series 1 is the brand blue. Each series has a Light and a Dark value, listed in the Tokens table, and the Dark values differ from Light. Two charts use the brand ramp instead of series colors: Area takes alpha 72, 48 and 24, and Heatmap takes alpha 24, 48 and 72 below chart/series-1. ## Sparkline and Legend Two pieces every chart reuses, published so a list row or a metric card can use them too. Legend is the color key, Sparkline is a trend line that carries shape and no values. Specimen: Legend, Horizontal and Vertical. Horizontal 361 by 52, Vertical 180 by 116. Specimen: Sparkline, Trend Up, Down and Flat, then Show Dot off. 64 by 20, line 1.5, dot 4. Use Horizontal under a wide chart and Vertical beside a Donut or Ring, and order the rows by value, largest first. All Sparkline trends share one vertical domain of 0 to 20, so a flat trend sits at mid height and a rising one never fills the box. Pair a Sparkline with the number it belongs to. ## Which parts build the charts? Five parts build the charts. They are underscore components, kept out of the published library, and an instance of each sits inside the charts above. Specimen: Tooltip, Point Below and Above. Tooltip 68 by 35.75, point 12, cell 16, column 40 by 184. Specimen: Point, Tone by State. Specimen: Cell, Level 0 to 4. Specimen: Column, Emphasis Solid then Soft, by Tone. Specimen: Grid. Point Dimmed is 35 percent opacity. Column has a 16 value slot over the bar and a 16 label under it, so a column is the bar plus 48. Give the column its height and the bar fills what is left. Put Grid behind the marks. ## Properties Each chart is one component with Show and text properties and no variants. Legend and Sparkline are sets, and the five parts are sets or components of their own. | Property | Type | Default | Charts that have it | | --- | --- | --- | --- | | `Show Header` | boolean | true | All but Donut and Ring | | `Label` | text | Per chart | All but Donut and Ring | | `Value` | text | Per chart | All but Donut and Ring | | `Show Context` | boolean | true | All but Donut and Ring. False by default on Gauge, Bullet, Heatmap, Scatter and Radar | | `Context` | text | Per chart | All but Donut and Ring | | `Show Gridlines` | boolean | true | Line, Area, Bar, Grouped, Stacked, Candlestick, Scatter | | `Show Labels` | boolean | true | Line, Area | | `Show Points` | boolean | true | Line | | `Show Tooltip` | boolean | true | Line, Area | | `Show Range` | boolean | true | Line, Area | | `Show Legend` | boolean | true | Grouped, Donut, Ring | | `Show Track` | boolean | false | Bar | | `Average` | boolean | true | Bar | | `Average Value` | text | Avg 1.7k | Bar | | Chart | Label | Value | Context | | --- | --- | --- | --- | | Line | Sessions | 18,204 | vs last week | | Area | Active users | 2,940 | vs last week | | Bar | Revenue this week | 11,720 | vs last week | | Bar - Grouped | Orders this week vs last | 1,284 | vs last week | | Bar - Stacked | Sessions by channel | 48,120 | vs last week | | Bar - Horizontal | Top sources | 9,410 | vs last month | | Waterfall | Net change | +1,860 | MRR this quarter | | Candlestick | BTC / EUR | 58,420 | this month | | Gauge | Storage used | 64.2 GB | of 100 GB | | Bullet | Against target | 3 of 5 on track | vs last quarter | | Funnel | Signup funnel | 8.3% end to end | vs last month | | Heatmap | Active days | 58 of 91 | Longest streak 12 days | | Scatter | Spend vs revenue | r = 0.82 | Strong correlation | | Radar | Squad profile | 78 overall | vs last season | | Set | Property | Values | Default | | --- | --- | --- | --- | | `Chart / Legend` | Orientation | Horizontal, Vertical | Horizontal | | `Sparkline` | Trend | Up, Down, Flat | Up | | `Sparkline` | Show Dot | boolean | true | | `_Chart Point` | Tone | Brand, Success, Error | Brand | | `_Chart Point` | State | Default, Dimmed | Default | | `_Chart Cell` | Level | 0, 1, 2, 3, 4 | 0 | | `_Chart Tooltip` | Point | Below, Above | Below | | `_Chart Tooltip` | Value | text | 12,480 | | `_Chart Column` | Tone | Brand, Neutral, Success, Error | Brand | | `_Chart Column` | Emphasis | Solid, Soft | Solid | | `_Chart Column` | Label, Value | text | Mon, 24 | | `_Chart Column` | Show Value | boolean | true | Line, Area, Stacked and Scatter draw a key row under the plot that has no property of its own. Read from the component property definitions of the Chart page on October 2, 2026. ## Tokens Series colors are their own variables, so a rebrand moves the charts with the rest of the kit. Everything else is a neutral or state token the components already use. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `chart/series-1` | #155DFC | #2B7FFF | First series: this week, Solid columns, Donut and Heatmap peak, Scatter New | | `chart/series-2` | #7D52F4 | #693EE0 | Second series: Donut, Stacked middle, Scatter Returning | | `chart/series-3` | #22D3BB | #1DAF9C | Third series: Donut, Stacked top | | `chart/series-4` | #FE9A00 | #E17100 | Fourth series | | `chart/muted` | #D1D1D6 | #6A7282 at 24% | Comparison period, last week bars, Other | | `chart/soft` | #DEDEE0 | #6A7282 at 24% | Columns at rest on Bar | | `brand/alpha-10` | #2B7FFF at 10% | #2B7FFF at 10% | Average pill, Funnel track, Scatter band | | `brand/alpha-16` | #2B7FFF at 16% | #2B7FFF at 16% | Radar fill, Ring Move track | | `brand/alpha-24` | #2B7FFF at 24% | #2B7FFF at 24% | Area third band, Heatmap level 1 | | `brand/alpha-48` | #2B7FFF at 48% | #2B7FFF at 48% | Area second band, Heatmap level 2 | | `brand/alpha-72` | #2B7FFF at 72% | #2B7FFF at 72% | Area first band, Heatmap level 3, Scatter trend | | `state/success/base-500` | #22C55E | #16A34A | Gains, up candles, target met, Ring Exercise, Trend Up | | `state/error/base-500` | #FB2C36 | #FB2C36 | Losses, down candles, target missed, Trend Down | | `state/warning/base-500` | #FF6900 | #F54900 | Ring Stand arc | | `state/success/lighter-50` | #F0FDF4 | #22C55E at 16% | Trend chip, Ring Exercise track | | `state/warning/lighter-50` | #FFF7ED | #FF6900 at 16% | Ring Stand track | | `state/success/dark-950` | #09361B | #86EFAC | Trend chip text and arrow | | `state/success/light-200` | #BBF7D0 | #22C55E at 24% | Column Success Soft | | `state/error/light-200` | #FFC9C9 | #FB2C36 at 24% | Column Error Soft | | `bg/soft-100` | #E9E9EA | #48484A | Gauge, Horizontal and Bullet tracks | | `bg/weak-50` | #F4F5F5 | #242427 | Heatmap level 0, Bar track, Range | | `bg/sub-300` | #C7C7CC | #8E8E93 | Column Neutral Solid | | `bg/white-0` | #FFFFFF | #0E0E0F | Surface: point rings, Area seams, tooltip text | | `border/sub-200` | #D1D1D6 | #48484A | Grid, cursor, connectors | | `border/soft-100` | #E9E9EA | #2F2F31 | Candlestick and Scatter gridlines, Radar rings | | `fg/strong-950` | #0E0E0F | #FFFFFF | Values, tooltip fill, Bullet tick | | `fg/sub-700` | #48484A | #C7C7CC | Titles, axis labels, legend labels | | `fg/soft-500` | #8E8E93 | #AEAEB2 | Axis ticks, Funnel drops, context text | | `text/on-color/strong` | #FFFFFF | #FFFFFF | Candlestick price tag | The header context text binds text/soft-500, which resolves to the same values as fg/soft-500. Read as bound variable names from the Chart page, Light and Dark, on October 2, 2026. ## How do the charts compare with Swift Charts and Material 3? Appetite UI draws its own charts, one set for both platforms. Apple ships charts as the Swift Charts framework and Material 3 publishes no chart component, so neither the iOS pages nor the Material 3 pages of the file carry a chart to mirror. | Appetite UI chart | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Line, Area, Bar, Grouped, Stacked | `LineMark`, `AreaMark`, `BarMark` in Swift Charts, code only | None | The weekly charts have no y axis. The value sits on the highlighted column and the plot keeps its 361. | | Donut | `SectorMark` in Swift Charts, code only | None | Four segments, 2 degrees apart, a 20 band on a 160 ring. | | Gauge | The SwiftUI `Gauge` view | None | A half circle 240 wide with a 20 band and a required real maximum. | | Scatter, Heatmap | `PointMark`, `RectMark` in Swift Charts | None | Cells of 22 on a five step brand ramp, dots 6 to 12 across with a surface ring. | | Ring, Bullet, Funnel, Waterfall, Candlestick, Radar, Sparkline | None as a component | None | Built in Appetite UI from the same header, grid and tokens as the rest. | Charts belong to the platform neutral data layer next to Table, and the drawing is the same on iOS and on Android. Apple's pages and the Material 3 pages in the Figma file have no chart, gauge or sparkline page, checked by name on October 2, 2026. ## How do I label a chart for accessibility? Give the plot an image role and a label that states the data, or put the values in a table beside it. A chart drawn as vectors is one picture to a screen reader, so the label has to carry what a sighted reader gets from the shapes. - **Write the label as data.** Give the chart type, the subject, the period and the one fact the highlight states. Every specimen above does it, for example "Line chart: sessions this week against last week, Monday to Sunday. The week peaks on Saturday at 3,200." - **Expose the values yourself.** On iOS use `accessibilityLabel` and `accessibilityValue` on each mark. On Android set `contentDescription` on the chart and a semantics node for each value. On the web give the svg `role="img"` and an `aria-label`, and keep a visually hidden table next to dense charts such as Heatmap, Scatter and Candlestick. - **Let color repeat a value.** Waterfall prints a plus or minus sign, Funnel prints its drop, Bullet prints the percent beside the bar, and Donut and Ring print every value in the legend. - **Mind the contrast of small labels.** In Light, the 12 point gain labels on Waterfall in state/success/base-500 measure 2.3 to 1 on white and the axis ticks in fg/soft-500 measure 3.3 to 1, so both repeat what a bar already says. A label that carries data on its own uses fg/sub-700 or fg/strong-950. - **Size the controls.** The Range row is a Segmented Control at Size Small with segments 30 high, and its hit area still has to reach 44 pt on iOS and 48 dp on Android, the platform/min-touch-target values. - **Respect reduced motion.** Draw the finished chart and skip the entrance. The specimens on this page play theirs only while prefers-reduced-motion allows motion, and otherwise open finished. If a reader needs a number, show it as text next to the chart. The specimens above are pictures: none takes focus, and the Range row is hidden from assistive technology. ## Guidelines Charts fail when they promise more than they can show. Keep to the limits each set states. - Do: Keep a Donut to four segments, largest first, starting at twelve o'clock. Group the tail as Other in chart/muted. - Avoid: Do not slice a Donut into seven. Past four segments a bar chart reads faster, because nobody compares seven angles. - Do: Use a Gauge when the maximum is real, like storage or a credit score. The range under the arc says what a full arc means. - Avoid: Do not draw a Gauge with an invented ceiling. With no real maximum, show the number alone: a made up maximum states a progress that does not exist. Grouped is two series at most and Stacked is three segments at most. Show the drop between Funnel steps as well as the totals, and stop at four steps on a phone. Tone a Bullet by whether the target was met. Pair every Sparkline with the number it belongs to. Count: 16 charts, plus Legend and Sparkline, on the Chart page of the Figma file. --- --- title: Checkbox description: Checkbox lets people select zero, one or several options. Appetite UI Figma component: off, on and mixed, five states, tokens and Material 3 notes. group: Components source: https://www.appetiteui.com/docs/checkbox dateModified: 2026-10-03 --- # Checkbox Updated: October 3, 2026. Checkbox is a form control for selecting one option, several, or none. ## Preview Default, on: a 24 pt box inside a 44 pt target, so the thing you can hit is bigger than the thing you can see. Click it. Specimen: State Default, Active True. 24 px box, radius 8, 2 px stroke, in a 44 px target. The 44 frame is the target and none of it is drawn. The box is 24 at radius 8 with a 2 stroke aligned inside. The tick is a custom vector, 11 by 8, stroked at 2.5 with round ends. Source: Checkbox, node 169:6573 of the Appetite UI Figma file, read on October 2, 2026. ## Which states does Checkbox have? Five: Default, Pressed, Focused, Error and Disabled, each crossed with off, on and mixed; the file has no Hover, so a pointer hover moves these specimens toward Pressed. While the finger is down an unchecked box strokes in brand, so the target confirms the touch before the value changes. Specimen: State x Active. Default, Pressed, Focused, Error, Disabled, each off, on and mixed. Focused is the focusRing/brand effect style, a 2 pt gap in the surface color and then a 2 pt ring in brand/base, drawn on the box. Error is for a required checkbox left empty: the stroke turns state/error/base-500 when off and the fill does when on or mixed. Mixed shows a 10 wide bar for a parent that has some children selected. The empty box strokes in bg/sub-200, so it stays visible on a white screen, and Disabled drops the stroke and paints bg/soft-100 whichever way it is set. 15 variants, State by Active, no holes. Source: the Checkbox set of the Appetite UI Figma file, read on October 2, 2026. ## Label The label is its own component: Align puts it on either side, and the description can be switched off. Each row is one checkbox, so click the text or the box. Specimen: Align Left, Align Right. 340 x 48, gap 16, title 18/28, description 14/20. The row is 340 by 48: the 44 wide Checkbox, 16 of gap, then 280 of text. The height comes from the text, 28 for the title at 18/28 Semi Bold plus 20 for the description at 14/20. Switching Show Description off takes the row to 44, the height of the box frame. Align swaps the order of the two children. ## Properties Two component sets: Checkbox, the box, and _Checkbox Label, the row that carries it. | Property | Type | Default | | --- | --- | --- | | `State` | Default \| Pressed \| Disabled \| Focused \| Error | Default | | `Active` | True \| False \| Mixed | False | | `Align` | Left \| Right | Left | | `Show Description` | Boolean | true | | `Label` | Text | Title of checkbox | | `Description` | Text | Insert the checkbox description here. | Checkbox carries no text. _Checkbox Label is two variants of Align and holds Label, Description and Show Description. The underscore keeps it out of the Assets panel, so copy the row from the Checkbox page of the file. ## Tokens Every value the checkbox reads, resolved through its aliases to the primitive underneath. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/white-0` | #FFFFFF | #0E0E0F | Fill when off, and the gap in the focus ring | | `bg/sub-200` | #D1D1D6 | #636366 | Stroke when off | | `brand/base` | #155DFC | #2B7FFF | Fill when on or mixed, stroke pressed and off, focus ring | | `brand/pressed` | #193CB8 | #155DFC | Fill pressed and on | | `state/error/base-500` | #FB2C36 | #FB2C36 | Error stroke when off, fill when on or mixed | | `bg/soft-100` | #E9E9EA | #48484A | Disabled fill | | `fg/disabled-400` | #AEAEB2 | #8E8E93 | Disabled tick and bar | | `icon/on-color` | #FFFFFF | #FFFFFF | Tick and bar | | `text/strong-950` | #0E0E0F | #FFFFFF | Label title | | `text/sub-700` | #48484A | #C7C7CC | Label description | brand/pressed is the pressed fill, darker than brand/base in both modes: #193CB8 in Light and #155DFC in Dark. icon/on-color is white in both modes, so the tick stays white on a dark screen. ## How does Checkbox differ on iOS and Material 3? iOS has no checkbox control, and Material 3 has one with a 48 by 48 target. Appetite UI Checkbox is one component with a 44 pt target for both. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Checkbox | None. iOS uses Toggle for one setting and a list row with a checkmark for a choice among several. | M3 / Checkbox, 48 by 48, State Unselected, Selected and Indeterminate by Is Enabled | Appetite UI draws a 24 box at radius 8 in a 44 target and adds Focused and Error. The Material 3 set has no Focused, Pressed or Error variant. | The 44 frame meets the iOS minimum touch target of 44 pt, set by `platform/min-touch-target` in the Platform collection. On Android, where the minimum is 48 dp, add 4 dp of hit area in code. ## Guidelines - Do: Put the consequence in the description. The title says what happens, the description says what it costs. - Avoid: Do not ship a checked box the user cannot uncheck. A choice with one option is not a choice, it is a sentence in the terms. Checkbox is for zero or more. For one setting that is on or off, use Toggle: a checkbox belongs in a form that submits, and a toggle applies the moment it moves. Make the whole label row tappable in code. --- --- title: Chip description: Chip is a compact capsule for filtering a list or showing an added entry. Appetite UI Figma component: five types, four states and tokens. group: Components source: https://www.appetiteui.com/docs/chip dateModified: 2026-10-03 --- # Chip Updated: October 3, 2026. Chip is a compact control for filtering a list, choosing from a set, or showing an entry someone added. ## Preview A compact capsule you can select or remove, for filters, tags and multi-select entry. For moving between views use Tab. Specimen: Chip, Type Default, State Default, Selected False. 99 x 32, capsule, padding 6 and 12, in a 99 x 44 hit frame. Click it. Selecting swaps bg/white-0 for bg/strong-950, turns the label text/white-0 and drops the outline. The chip is a capsule with a border/sub-200 outline, and a 44 high hit frame surrounds the 32 high chip, so the tap target is bigger than the shape. ## Which types does Chip have? Chip has five types, each leading with a different element. The axis changes the element in front of the label and nothing else: no color, no height, no radius. Specimen: Type Default, Avatar, Emoji, Flag, Brand. 16 box on Default, 20 on the other four. The bigger box costs left padding: 12 on Type Default, 6 on the four that lead with 20, so the chip measures 99 then 97. Brand leads with a company mark from the Brands set, Slack by default. ## How does a selected Chip look? Selected fills the whole capsule, so a row of chips reads at a glance. It is one boolean axis. Specimen: Selected False, Selected True. bg/white-0 to bg/strong-950, label to text/white-0. Both tokens invert with the theme: a selected chip is a near black capsule with white text in light and a white capsule with near black text in dark. Selected True keeps the dark fill in Default, Pressed and Focused, and only the overlay and the ring change. ## Which states does Chip have? Four states, on an unselected and a selected chip; there is no Hover, so a pointer hover on a specimen shows Pressed. Disabled fades the outline, the label and both icons, and a selected chip drops to bg/soft-100. Specimen: State Default, Pressed, Focused, Disabled, on Selected False and Selected True. bg/white-0, bg/weak-50, bg/soft-100 with the ring, then text/disabled-400 inside a border/soft-100 outline. Focused uses the focusRing/brand effect style: from the edge out, a 1 pt brand/base stroke, a gap in the surface color and a 2 pt ring in brand/base. The fill turns bg/soft-100 when the chip is unselected. Selected Pressed lays state/pressed/on-strong at 10 percent over the dark fill. The close x is fg/soft-500 in every state but Disabled, so it stays visible on a selected chip and in dark mode. Disabled unselected keeps bg/white-0 and moves the outline to border/soft-100. Disabled selected drops to bg/soft-100 and is the one selected chip that does not take bg/strong-950. Pressed keeps the outline on Type Default and drops it on the other four. Focused pushes the left padding from 6 to 8 on Emoji, Flag and Brand but not on Avatar, so those three measure 99 where they rest at 97. 40 variants: State by Type by Selected, with no holes. ## How do I hide the icon or the close button? Turn Icon off for a plain filter and Close Button off when the chip is a label. Both booleans are true by default. Specimen: Both true, Icon false, Close Button false, both false. 99, 83, 83, 67. The widths are arithmetic: 12 of padding, a 16 box, the label wrapper at 6 plus 31 plus 6, another 16 box, 12 of padding. Drop either box and 16 goes with it. ## Properties Three variant axes and four instance properties. Four states by five types by two selections make 40 variants, and the set holds all of them. | Property | Type | Default | | --- | --- | --- | | `State` | Default \| Pressed \| Focused \| Disabled | Default | | `Type` | Default \| Avatar \| Emoji \| Flag \| Brand | Default | | `Selected` | False \| True | False | | `Text` | Text | Chip | | `Icon` | Boolean | true | | `Close Button` | Boolean | true | | `Icon Swap` | Instance swap, the Icons set | circle | Source: the Chip page of the Appetite UI Figma file, read on October 2, 2026. ## Tokens Every value the component reads, resolved through its aliases to the Foundations primitive. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/white-0` | #FFFFFF | #0E0E0F | Fill at rest and while disabled, and the gap in the focus ring | | `border/sub-200` | #D1D1D6 | #48484A | 1 pt inside outline, unselected | | `border/soft-100` | #E9E9EA | #2F2F31 | Outline while disabled | | `bg/weak-50` | #F4F5F5 | #242427 | Pressed, unselected | | `bg/soft-100` | #E9E9EA | #48484A | Focused unselected, and the selected disabled chip | | `bg/strong-950` | #0E0E0F | #FFFFFF | Selected, except while disabled | | `state/pressed/on-strong` | #FFFFFF at 10% | #030712 at 10% | Overlay on a selected chip while pressed | | `brand/base` | #155DFC | #2B7FFF | Focused stroke and ring | | `text/sub-700` | #48484A | #C7C7CC | Label, unselected | | `text/white-0` | #FFFFFF | #0E0E0F | Label, selected | | `text/disabled-400` | #AEAEB2 | #8E8E93 | Label, disabled | | `fg/soft-500` | #8E8E93 | #AEAEB2 | Leading icon and close x | | `fg/disabled-400` | #AEAEB2 | #8E8E93 | Both icons while disabled | | `colors/gray/200` | #D1D1D6 | #D1D1D6 | Avatar disc, one mode | Geometry runs on `dimensions/radius/full` 9999, `dimensions/spacing/3` 12, `dimensions/spacing/1-5` 6 and `dimensions/icon/stroke` 1.5 on the icon boxes. ## How does Chip differ on iOS and Material 3? iOS has no chip control, and Material 3 has one with four types and a 32 high rounded rectangle. Appetite UI Chip is a capsule on both platforms. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Chip | None. iOS filters with a segmented control, a menu or a bordered button. | M3 / Chip, 32 high at radius 8, Type Assist, Filter, Input and Suggestion by Selected | Appetite UI is a capsule at radius 9999 with an avatar, emoji, flag or brand lead and adds Pressed, Focused and Disabled. The Material 3 set draws no state variants. | The 44 high hit frame meets the iOS minimum touch target of 44 pt, set by `platform/min-touch-target` in the Platform collection. On Android, where the minimum is 48 dp, add 4 dp of hit area in code. ## When should I use a Chip? Use chips to filter a list, choose from a set or show an entry someone added. - Do: Use a row of chips as a filter set and let selection carry the state. Drop the close button when nothing is being removed. - Avoid: Do not move between views with chips. That is Tab, which owns the underline, the swipe and the screen it belongs to. Keep the label short enough to stay on one line. The chip hugs its text and never wraps, so a long label pushes the row into a horizontal scroll. --- --- title: Context Menu description: Context Menu lists the actions for one object after a press and hold. Appetite UI Figma component: item states, a preview slot and tokens. group: Components source: https://www.appetiteui.com/docs/context-menu dateModified: 2026-10-03 --- # Context Menu Updated: October 3, 2026. Context Menu lists the actions for one object when someone presses and holds it, without leaving the screen. ## Preview Actions for one specific object, raised by press and hold: .contextMenu on iOS, a long press opening a DropdownMenu on Android. Press a row to see it fill. Specimen: Context Menu, Slot False. 300 x 307, padding 8, gap 2, radius 32. The menu is 307 tall: 8 of padding, five rows of 56, five gaps of 2, the 1 separator, 8 again. Each row takes its icon from Icon Swap, so the menu above shows share, link, pencil, star and trash. The menu surface is bg/raised, the token for floating surfaces: white in light and #242427 in dark, so the menu separates from a dark screen. Source: Figma sets Context Menu and _Context Menu Item, read October 2, 2026. ## Which states does a Context Menu item have? Four: Default, Pressed, Destructive and Disabled, and only Pressed paints a fill. The item is the building block behind every row and sits only inside the menu. Specimen: State Default, Pressed, Destructive, Disabled. 284 x 56, padding 6 and 16, gap 12, radius 24. Default carries no fill, so a row is invisible until pressed, and Pressed takes bg/weak-50. Destructive takes state/error/base-500 on both the label and the icon, and belongs last, under a separator. Disabled takes fg/disabled-400 and text/disabled-400, which resolve to the same primitive in both modes. A standalone item is 276 wide and stretches to 284 inside the menu. ## What does Slot True add to a Context Menu? Slot True raises the pressed object above the menu, which is the iOS convention and reads well on both platforms. It is the one boolean axis. Specimen: Slot True. 160 plus 8 plus 307 = 475. The slot ships empty and the object is yours to place. It is 160 tall with 8 between it and the menu, which is shortened here. ## Properties One axis on the published component and a slot. The rest sit on the item inside it, a building block used only within the menu. | Property | Type | Default | | --- | --- | --- | | `Slot` | Variant: False \| True | False | | `Preview` | Slot, 300 x 160 | empty | | `State` | Variant on the item: Default \| Pressed \| Destructive \| Disabled | Default | | `Label Text` | Text, on the item | Menu item | | `Icon Swap` | Instance swap, on the item | share-2 | Context Menu ships 2 variants and the item ships 4. The menu composes five items and a separator, so a change to the item reaches every row of both variants. ## Tokens Every value the component reads, resolved through its aliases to the Foundations primitive. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/raised` | #FFFFFF | #242427 | The menu surface | | `border/soft-100` | #E9E9EA | #2F2F31 | 1px inside stroke, and the separator | | `bg/weak-50` | #F4F5F5 | #242427 | Pressed row | | `text/strong-950` | #0E0E0F | #FFFFFF | Label | | `fg/sub-700` | #48484A | #C7C7CC | Icon | | `state/error/base-500` | #FB2C36 | #FB2C36 | Destructive label and icon | | `text/disabled-400` | #AEAEB2 | #8E8E93 | Disabled label | | `fg/disabled-400` | #AEAEB2 | #8E8E93 | Disabled icon | The shadow is the effect style `dropShadow/lg`: 0 12 18 at minus 3 on black at 8 percent, over 0 5 6 at minus 5 on black at 5 percent. Geometry runs on `dimensions/radius/3xl` 32 for the menu and `dimensions/radius/2xl` 24 for the row, with `dimensions/spacing/2` 8, `dimensions/spacing/0-5` 2, `dimensions/spacing/4` 16, `dimensions/spacing/3` 12 and `dimensions/spacing/1-5` 6. ## How does Context Menu differ on iOS and Material 3? iOS has its own Menu set in the file, 238 wide with three to five items. Material 3 has no menu set in the file, and Android raises the same actions with a long press and a DropdownMenu. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Context Menu | iOS / Menu: Items 3, 4 or 5, optional section title, optional quick action row, in the iOS glass material. Items are 40 tall. | None in the file. In code, a Compose DropdownMenu opened by a long press. | Appetite UI is 300 wide with 56 tall rows and a preview slot above the menu. It has no quick action row and no submenu, and the Pressed row paints bg/weak-50 where iOS paints glass. | Every row is 56 tall, above the minimum touch target of 44 pt on iOS and 48 dp on Android, which comes from `platform/min-touch-target` in the Platform collection. ## Guidelines - Do: Put the destructive action last, below a separator, and cap the menu at about seven rows. - Avoid: Do not open with the destructive row, and do not let this menu be the only way to reach an action. Press and hold is not discoverable, so everything here must also exist somewhere visible. The menu belongs to one object, not to the screen. Actions that apply to the whole view belong in a toolbar or an action sheet. --- --- title: Divider description: Divider separates content into groups with a single line: horizontal, with a label, or vertical. Appetite UI component for Figma, iOS and Android. group: Components source: https://www.appetiteui.com/docs/divider dateModified: 2026-10-03 --- # Divider Updated: October 3, 2026. Divider separates content into groups with a single line. Use it where spacing alone stops doing the work. ## Preview A visual separator, the smallest component in the system: one color, one weight, three shapes. On iOS this is Divider, on Android HorizontalDivider and VerticalDivider. Specimen: Divider, Style Horizontal. 342 x 4, a 1px line with 2 above and below. The frame measures 4 and the line measures 1, with 2 of padding above and below it. ## Which Divider styles are there? Three shapes on one axis. Horizontal rules off a block, With Label carries a word between two options, Vertical splits items sitting on one line. Specimen: Style Horizontal, With Label, Vertical. 342 x 4, 342 x 16, 1 x 24. With Label splits the 342 into 153, the label, 153, with 12 of gap on each side. The label is the only part that is not the line color: it takes `text/soft-500` where the line takes `border/soft-100`. ## Where does each Divider style belong? Each style exists for one job. Seen on its own a divider is a gray line, seen in place it is the reason two things read as separate. Specimen: Horizontal between rows, With Label between actions, Vertical in a meta line. the blocks around them are stand-ins, not Button. The set has no Inset style for a list with a leading avatar. Start the line past the avatar in your own layout, as a layout choice. ## How does Divider differ on iOS and Material 3? Neither platform has a standalone divider component in the Figma file, and native lists draw their own separators. Compose has HorizontalDivider and VerticalDivider, SwiftUI has Divider. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Divider, Horizontal 342 x 4 and Vertical 1 x 24 | SwiftUI Divider and list separators | Compose HorizontalDivider and VerticalDivider | Same job on every platform. Appetite UI draws one line weight in `border/soft-100` on both | | Divider, With Label 342 x 16 | No counterpart | No counterpart | A word between two options has no native component, so this style is Appetite UI's own | A divider is decorative, so no touch target applies. Mark it as a separator for assistive technology only when it separates groups a reader moves between, and leave it out of the reading order when it is purely visual. The line, `border/soft-100` on white, is meant to be quiet and is not a contrast carrier: never use it as the only cue that two things are different. ## Properties One axis and one text field, and nothing else is exposed. | Property | Type | Default | | --- | --- | --- | | `Style` | Horizontal \| With Label \| Vertical | Horizontal | | `Text` | Text, With Label only | or | | Style | Size | Built from | | --- | --- | --- | | Horizontal | 342 x 4 | 2 of padding, a 0 tall line, 2 of padding | | With Label | 342 x 16 | 153, gap 12, the label, gap 12, 153 | | Vertical | 1 x 24 | the same line, rotated, length 24 | The width is fixed at 342 on both horizontal styles, which is a 390 screen less 24 of side margin on each edge. Set it to fill in your own layout: nothing in the component depends on the number. ## Tokens Two values for the whole component. There is no second color, no weight scale and no emphasis variant. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `border/soft-100` | #E9E9EA | #2F2F31 | Every line, all three styles | | `text/soft-500` | #8E8E93 | #AEAEB2 | The label on With Label | The label runs on `typography/fontSize/xs` 12, `typography/lineHeight/xs` 16 and `typography/letterSpacing/wide` .1 at the default weight. Geometry runs on `dimensions/spacing/0-5` 2, `dimensions/spacing/3` 12 and `dimensions/spacing/6` 24. The label, `text/soft-500` on white, measures 3.26 to 1, so give a label that carries meaning 4.5 to 1 in your product. A divider takes no focus, and the 44 pt target applies to the controls on either side of it. ## Guidelines - Do: Use it where spacing alone stops doing the work: rows of the same weight, or two options that need a word between them. - Avoid: Do not rule off every element. A divider after each row, plus one under the last, turns a list into a table nobody asked for. A section that already sits on its own card does not need a divider above it. The card edge is the separation. --- --- title: Drawer description: Drawer slides navigation in from the edge and pushes the screen aside. Appetite UI Figma component: five layouts, one row in three sizes and four states. group: Components source: https://www.appetiteui.com/docs/drawer dateModified: 2026-10-03 --- # Drawer Updated: October 3, 2026. Drawer holds navigation off screen and slides it in when you need it, pushing the screen aside as a card. ## Preview The drawer opens at the leading edge and the screen moves aside as a rounded card. Open it from the button, and dismiss it by tapping what is left of the screen or with Escape. Specimen: Navigation Drawer, Layout Sections, open. 300 x 852 drawer over a 393 wide screen, no corners of its own. The drawer is a fixed 852 high and 300 wide, padded 64 12 32 12, and has no rounded corners of its own because its leading edge sits off screen. Sections and Compact pin two actions to the bottom edge of the 852, over a fade, so the list scrolls underneath them. The block pads its bottom by `grid/safe-area/bottom`, which is 34 on iPhone and 24 on Android, so the buttons clear the home indicator and the gesture bar. Opening the drawer pushes the screen 300 to the right, and 93 of it stays in view as a card at radius 44 with a 1 hairline and `dropShadow/2xl`. The drawer under it carries `dropShadow/lg` in the example screens. Source: the Navigation Drawer set of the Appetite UI Figma file, read on October 2, 2026. ## Which layouts does Drawer have? Five layouts share one shell and one row component. Pick the layout by what your app puts first: destinations, conversations, a person, your own content, or a workspace. Specimen: Layout Sections, Compact, Profile, Slot, Workspace. 300 x 852, padding 64 12 32, gap 16. | Layout | What it holds | Use it for | | --- | --- | --- | | Sections | A Top row with a title and search, six icon rows, a Recents group, and two pinned actions | An app with a few destinations and a history | | Compact | A Top row, groups named Today, Yesterday and Previous 7 days with text only rows, and two pinned actions | A chat list | | Profile | A profile block with avatar, name, handle and stats, six Large rows, three rows with a Chevron, and two utility buttons | A drawer that leads with the account | | Slot | A Top row, a native slot 276 wide and 636 high, and an Account row | Content of your own between the two | | Workspace | A workspace switcher and a new page button, Quick rows, and Favorites, Teamspaces and Private groups with nested rows | Apps built around pages and teams | Slot is a native Figma slot between the Top row and the Account row, and everything in it is yours to fill. The pink dashes in the specimen mark the empty slot and are not part of the component. Icons swapped into a row keep their own ink: fg/sub-700 in Sections, fg/strong-950 in Profile and Workspace, and a state color on five Workspace rows. The Navigation Drawer set holds 5 layouts. ## How tall is a Drawer row? A row, the internal _Drawer Item, is 44, 48 or 52 high. Every line in a layout is that one component, on three axes: Size sets the height, State says how the row is doing, Trailing says what it opens. Specimen: Size, State, Trailing. 44 / 48 / 52 high, radius 12, gap 12 / 12 / 16, label 16 / 18 / 20. Small is 44 high with a 16/24 label and its icon at 20, Default is 48 with 18/28 and its icon at 24, and Large is 52 with a 20/28 Semi Bold label and its icon at 24 on fg/strong-950. The radius is 12 on all of them. Pressed is bg/soft-100 and Active is bg/weak-50, and Active lifts the icon to fg/strong-950 without changing the weight. Accent turns the icon and the label brand/base on no fill, with the label Semi Bold on Small and Large and Regular on Default. More and Badge pull the right padding from 12 to 8. A Badge trailing holds a Badge at State Information, Type Pill, Style Color, with a count. The Chevron and More glyphs stay on fg/soft-500 in every state, so the trailing mark never carries the state. A Chevron points down on an expanded row, as on Design in the Workspace layout. Source: the _Drawer Item set of the Appetite UI Figma file, read on October 3, 2026. ## Properties The row carries the properties. The drawer has one variant axis and one slot. | Set | Property | Type | Default | | --- | --- | --- | --- | | Navigation Drawer | `Layout` | Sections \| Compact \| Profile \| Slot \| Workspace | Sections | | Navigation Drawer | `Slot` | Slot | empty | | _Drawer Item | `Size` | Default \| Large \| Small | Small | | _Drawer Item | `Trailing` | None \| Chevron \| More \| Badge | None | | _Drawer Item | `State` | Default \| Pressed \| Active \| Accent | Default | | _Drawer Item | `Label` | Text | Drawer item | | _Drawer Item | `Icon` | Boolean | true | | _Drawer Item | `Icon Swap` | Instance swap | folder | Label is one line and truncates rather than wraps. Icon turns the leading slot off, which is how the Recents and chat rows run. _Drawer Item holds 48 variants: Size by Trailing by State, with no holes. The underscore keeps it out of the Assets panel, so it reaches you inside the five layouts. ## Tokens Every color is bound to a variable and turns with the mode. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/white-0` | #FFFFFF | #0E0E0F | The drawer and the Actions surface | | `bg/weak-50` | #F4F5F5 | #242427 | Active row | | `bg/soft-100` | #E9E9EA | #48484A | Pressed row | | `border/soft-100` | #E9E9EA | #2F2F31 | Divider and the Outline icon button | | `brand/base` | #155DFC | #2B7FFF | Accent row, workspace mark, Chat button | | `fg/strong-950, text/strong-950` | #0E0E0F | #FFFFFF | Titles, labels, an Active icon | | `fg/sub-700` | #48484A | #C7C7CC | Icon at rest | | `fg/soft-500, text/soft-500` | #8E8E93 | #AEAEB2 | Chevron, More, plan line, small headers | | `state/information/base-500` | #155DFC | #155DFC | Badge, one value in both modes | | `text/on-color/strong` | #FFFFFF | #FFFFFF | Badge count | The pushed screen card is radius 44 on `bg/white-0` with a `border/soft-100` hairline. The row radius 12 is `dimensions/radius/lg`, the top padding of 64 is `dimensions/spacing/16`, and a Badge casts `dropShadow/xs`. Row icons are stroke 1.75, the Profile and Workspace icons 2, and the badge-check beside the Profile name is 1.5 on `brand/base`. ## How does Drawer differ on iOS and Material 3? Apple and Material both favor a bar over a drawer for primary navigation. Appetite UI Drawer is for the app that keeps destinations, history or a workspace off screen. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Navigation Drawer | None in the Apple Platform pages. iOS puts primary destinations in iOS / Tab Bar. | None in the Material 3 pages. The nearest are M3 / Navigation bar and M3 / Side Sheet, 320 wide in Standard and Modal. | Appetite UI Drawer is 300 wide with five layouts and a pinned action block, and it is built for the leading edge on both platforms. | A row is 44, 48 or 52 high. Small clears the 44 pt minimum touch target on iOS and sits under the 48 dp one on Android, both in `platform/min-touch-target`, so on Android use Default or Large. ## When should I use a Drawer? Use a Drawer when an app keeps destinations, history or a workspace off screen. Two emphasis states, used once each, keep it readable. - Do: One Accent row for the action that starts something, one Active row for the conversation on screen. - Avoid: Accent on more than one row. Emphasis spread across the list is emphasis spent, and the row that acts stops standing out. Pick the trailing mark for the gesture: a Chevron on a row that opens another list, More on a row with its own menu, a Badge for a count, nothing on a row that simply goes somewhere. Rows in a history run with Icon off, so the entries read as text. --- --- title: Dropdown description: Dropdown opens a short menu of options anchored to the control that opened it. A Figma menu with Open and Close states, four option states and a popover. group: Components source: https://www.appetiteui.com/docs/dropdown dateModified: 2026-10-03 --- # Dropdown Updated: October 3, 2026. Dropdown opens a short menu of options, anchored to the control that opened it, and closes again when a choice is made. ## Preview A menu anchored to a trigger. Press the label to open it, press an option to choose it and press Escape to close it. Specimen: DropdownMenu, State Close then Open. trigger 44 tall, menu 300 x 296. Closed, the trigger has no fill; open, it takes bg/soft-100 and the chevron turns up. With a title and four rows the menu is 300 wide and 296 tall. The menu is a floating surface on bg/raised, white in Light and #242427 in Dark, with a 1 pt edge and dropShadow/md. The menu title and the option descriptions are `text/soft-500`, #8E8E93, which measures 3.26 to 1 on white and 2.99 to 1 on the Active row, under the 4.5 to 1 that WCAG asks of small text. In code, give the trigger a visible focus ring, move focus into the menu when it opens and back to the trigger when it closes, and let the arrow keys move between rows. The trigger is 44 tall and a row 56: both clear the 44 pt iOS minimum, and the trigger needs 4 dp more hit area on Android. ## Which states does a Dropdown option have? Four: Default, Active, Pressed and Checked. The option is the building block behind every row, and Checked adds a brand check after the text. Specimen: State Default, Active, Pressed, Checked. 276 x 56, radius 12, padding 6 and 16, gap 12. The option radius is 12, concentric with the 24 menu radius and its 12 of padding. Menu and option sit on bg/raised, and the icons are strokes at 1.75 on the 20 option icon and the check, 1.5 on the 16 chevron. Pressed is darker than Active, the reverse of Context Menu where Pressed takes bg/weak-50. On a pointer, hovering a row shows Active and pressing it shows Pressed. ## Only Popover The second axis drops the trigger and ships the menu alone, for anchoring to something the component does not own: an icon button, a row, a long press. Specimen: Only Popover True. 300 x 296, no trigger above it. A closed popover would be nothing on screen, so the file draws three of the four State and Only Popover pairs. ## When should I use a Dropdown? Use a Dropdown for a short list of up to about six options that belong to one trigger. For a longer list on a phone, use Action Sheet or Picker. A dropdown keeps the choice next to the control that asked for it, so the person never loses the screen behind it. Checked marks the current choice. When the thing being chosen has no trigger on screen, use Only Popover rather than a dropdown with an invisible button. When the list is long or needs a search, a [Picker](https://www.appetiteui.com/docs/picker) or an [Action Sheet](https://www.appetiteui.com/docs/action-sheet) is faster to scan with a thumb. ## How does Dropdown differ on iOS and Material 3? iOS draws a menu as a narrow glass panel at radius 32 and Material 3 has no menu in the file. Appetite UI draws a 300 wide surface at radius 24 with a title row and rows 56 tall. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | `DropdownMenu` | `iOS / Menu`, 238 wide at radius 32 with 3, 4 or 5 items and an optional quick action row | None in the file. Compose uses DropdownMenu. | Appetite UI adds a title row, a description line and a Checked state. Rows are 56 tall against 40 on iOS. | | `Only Popover` | `iOS / Contextual Menu`, a menu under a raised preview of the pressed item | None in the file | The Appetite UI popover anchors to any control and shows no preview. | The 56 option row clears both minimums in `platform/min-touch-target`, 44 pt on iOS and 48 dp on Android; the 44 trigger clears iOS, so add 4 dp of hit area on Android. Read [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge) for how one screen switches between the two, and [iOS](https://www.appetiteui.com/docs/ios) for the platform mirrors. ## Properties Two variant properties, a boolean and a text on the menu, and six properties on the option inside it, each with its options from the component definition. | Set | Property | Type | Options | Default | | --- | --- | --- | --- | --- | | DropdownMenu | `State` | Variant | Open, Close | Close | | DropdownMenu | `Only Popover` | Variant | False, True | False | | DropdownMenu | `Title` | Boolean | on, off | on | | DropdownMenu | `Title Text` | Text | any string | Dropdown title | | _Dropdown Option | `State` | Variant | Default, Active, Pressed, Checked | Default | | _Dropdown Option | `Icon`, `Description` | Boolean | on, off | on | | _Dropdown Option | `Menu Text`, `Description Text` | Text | any string | Dropdown option, Description | | _Dropdown Option | `Icon Swap` | Instance swap | any icon | circle | DropdownMenu ships 3 variants. The option ships 4 and is composed four times into each open menu. Source: DropdownMenu and _Dropdown Option of the Appetite UI Figma file, read on October 2, 2026. ## Tokens Every value the component reads, resolved through its aliases to the Foundations primitive. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/raised` | #FFFFFF | #242427 | Menu surface, and the option at rest and Checked | | `border/soft-100` | #E9E9EA | #2F2F31 | 1 pt inside stroke on the menu | | `bg/soft-100` | #E9E9EA | #48484A | Open trigger, and the Pressed option | | `bg/weak-50` | #F4F5F5 | #242427 | Active option | | `text/sub-700` | #48484A | #C7C7CC | Trigger label | | `text/strong-950` | #0E0E0F | #FFFFFF | Option title | | `text/soft-500` | #8E8E93 | #AEAEB2 | Menu title and option description | | `fg/soft-500` | #8E8E93 | #AEAEB2 | Chevron and option icon | | `brand/base` | #155DFC | #2B7FFF | The check on Checked | The shadow is the effect style `dropShadow/md`: 0 10 15 at minus 3 on black at 5 percent, over 0 4 6 at minus 4 on black at 8 percent. The menu radius is 24, the option and trigger radius 12, and the trigger height 44. ## Guidelines - Do: Keep it to a handful of options and let the title say what the list is for. Checked marks the current choice, so the menu answers its own question. - Avoid: Do not use it for a long list. Past about six options on a phone the component's own description sends you to Action Sheet or Picker. Make the trigger say what is chosen, because the menu closes after a pick and the component has no value slot of its own. --- --- title: File Upload description: File Upload lets people add a photo or a document, then shows progress, success and errors. Six states in Figma, with tokens and iOS and Android notes. group: Components source: https://www.appetiteui.com/docs/file-upload dateModified: 2026-10-03 --- # File Upload Updated: October 3, 2026. File Upload is where a person adds a photo or a document. After that it reports progress, success and failure. ## Preview A drop zone for photos and documents: Default invites the first tap and offers camera, photo library and files as sources, and Active marks the press or drag-over. Press it to run the whole cycle. Specimen: File Upload, press to run the cycle. Zone 361 x 212, row 361 x 72, radius 16, dash 6 on 4 at 1. The cycle runs Default, Active, Uploading, Upload in that order, and a press during the run starts over. The set draws two shapes: the drop zone stays until a file is chosen, then the component shrinks to a file row, so a finished upload takes less room than the invitation to add one. The progress bar, the file name and a round action, Cancel, Remove or Retry, live in that row. The supporting text and the meta line are `fg/soft-500`, #8E8E93, which measures 3.26 to 1 on white and 2.99 to 1 on the bg/weak-50 zone, under the 4.5 to 1 that WCAG asks of small text. In code, make the whole zone one button with a visible focus ring that opens the system picker. The zone is 361 by 212, far above the minimum touch target, while the source pills and the round actions are 36 and need a larger hit area. Source: the File Upload set of the Appetite UI Figma file, read on October 2, 2026. ## Which states does File Upload have? Six states in two shapes: Default, Active and Disabled are the drop zone, and Uploading, Upload and Error are the file row. The rows differ only in what the second line says and which action sits at the end. Specimen: State Default, Active, Disabled, Uploading, Upload, Error. zone 361 x 212 padding 24, row 361 x 72 padding 16 8 16 16. The three zone states share one shape and change the paint. Active fills the zone with brand at 10 percent alpha, draws the dashed edge in brand and turns the featured circle brand with a white icon. Disabled keeps the dashed edge on border/soft-100 and moves every ink to fg/disabled-400. The row states share a second shape. Uploading shows the file name, a meta line with the amount sent and a 4 high progress bar. Upload swaps the bar for a green check and the word Uploaded, and Remove replaces Cancel. Error moves the stroke, the file tile and the meta line to the error colors, keeps the name, and offers Retry. ## Which properties does File Upload have? One variant axis and three text properties. The zone reads Label and Supporting Text, the row reads File Name. | Property | Type | Default | | --- | --- | --- | | `State` | Default \| Active \| Uploading \| Error \| Disabled \| Upload | Default | | `Label` | Text, on the drop zone | Upload a file | | `Supporting Text` | Text, on the drop zone | PNG, JPG or PDF, up to 10 MB | | `File Name` | Text, on the file row | brief.pdf | | State | Shape | Fill | Edge | Leading and meta | | --- | --- | --- | --- | --- | | Default | Zone 361 x 212 | bg/weak-50 | dashed border/sub-200 | cloud-upload in brand/base on a white circle, three source pills | | Active | Zone 361 x 212 | brand/alpha-10 | dashed brand/base | the same, on a brand circle with a white icon | | Disabled | Zone 361 x 212 | bg/weak-50 | dashed border/soft-100 | every ink fg/disabled-400 | | Uploading | Row 361 x 72 | bg/white-0 | solid border/soft-100 | file tile, name, amount sent, progress bar, Cancel | | Upload | Row 361 x 72 | bg/white-0 | solid border/soft-100 | file tile, name, green check and Uploaded, Remove | | Error | Row 361 x 72 | bg/white-0 | solid state/error/light-200 | error tile, name, the reason in state/error/base-500, Retry | The meta line, the source pills and the actions are layers inside the set and carry no property; the pills are Button instances at Neutral, Outline, sm. Change the meta text on the instance, and show or hide a source by editing the Sources row. ## Tokens Every value the component reads, resolved through its aliases in Light and Dark. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/weak-50` | #F4F5F5 | #242427 | Zone fill and the file tile | | `bg/white-0` | #FFFFFF | #0E0E0F | Row fill, the featured circle at rest and the source pills | | `border/sub-200` | #D1D1D6 | #48484A | Dashed edge at rest | | `border/soft-100` | #E9E9EA | #2F2F31 | Row stroke, pill stroke and the Disabled dashed edge | | `brand/base` | #155DFC | #2B7FFF | Active edge and circle, the icon at rest, the progress fill | | `brand/alpha-10` | #2B7FFF at 10% | #2B7FFF at 10% | Active fill | | `bg/soft-100` | #E9E9EA | #48484A | Progress track and the Disabled circle | | `fg/strong-950` | #0E0E0F | #FFFFFF | Label and file name | | `fg/soft-500` | #8E8E93 | #AEAEB2 | Supporting text and meta | | `text/sub-700` | #48484A | #C7C7CC | Pill labels | | `fg/sub-700` | #48484A | #C7C7CC | Pill icons, tile icon, action icon | | `text/on-color/strong` | #FFFFFF | #FFFFFF | Icon on the Active circle | | `fg/disabled-400` | #AEAEB2 | #8E8E93 | Every ink on Disabled | | `state/success/base-500` | #22C55E | #16A34A | Check beside Uploaded | | `state/error/light-200` | #FFC9C9 | #FB2C36 at 24% | Error stroke | | `state/error/lighter-50` | #FEF2F2 | #FB2C36 at 16% | Error tile | | `state/error/base-500` | #FB2C36 | #FB2C36 | Error icon and reason | | `dropShadow/xs` | effect | effect | Featured circle at rest | The edge is 1 wide in every state and drawn inside the frame, so it never changes the size. Source: the Color Tokens collection of the Appetite UI Figma file, read on October 2, 2026. ## How does File Upload differ on iOS and Material 3? File Upload has no counterpart in the iOS or Material 3 pages of the file, because both platforms hand file selection to a system picker. Build the surface here and let it open the picker. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | File Upload | None in the kit. SwiftUI offers PhotosPicker and fileImporter | None in the kit. Android offers the Photo Picker and GetContent | The system pickers draw the chooser. File Upload draws the surface that opens it and the progress after it, and the three sources map onto the pickers. | The source pills and the round actions are 36 high, under the minimum touch target of 44 pt on iOS and 48 dp on Android set by `platform/min-touch-target`, so add hit area in code. The whole drop zone is the larger target for the first tap. See [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge), [iOS](https://www.appetiteui.com/docs/ios) and [Material 3](https://www.appetiteui.com/docs/material-3) for how the same component adopts each platform. ## Guidelines - Do: Put the reason on the meta line. The state has a place for the message, so use it instead of a toast that leaves. - Avoid: Do not leave the supporting line empty. What you accept and how big it can be is the one thing the user needs before they choose. Uploading, Upload and Error are answers from the server, so wire State to the real request. A row that says Uploading while nothing is in flight is worse than no state at all. Tell assistive technology what happened. Announce Uploading and Upload in a polite live region and Error in an assertive one with the reason, and keep the progress amount as text, which the meta line already is. --- --- title: Input description: Input collects text, passwords, numbers, codes and messages. Figma component with six text types, Text Area, Chip, Counter, Digit, Stepper and Composer. group: Components source: https://www.appetiteui.com/docs/input dateModified: 2026-10-03 --- # Input Updated: October 3, 2026. Input collects one line of text, a password, a number, a code or a message, with a label, a hint and an error that never change the height of the field. ## Preview The field is 56 pt tall in every state, 104 with its label and hint, and underlined: one rule on the bottom edge and no fill or radius. Type in it. Specimen: Type Default, State Placeholder. 340 x 104, label 20, field 56, hint 16, gap 6. ## Which types does Input have? Input has six types: Default, Left Selection, Right Selection, Password, Prefix and Suffix. Default is a plain field, and Left and Right Selection put a picker on one side of a divider, for a dial code or a currency. Specimen: Type. Default, Left Selection, Right Selection, Password, Prefix, Suffix. Password leads with a lock and ends on an eye-off icon, which in the specimen above is a switch that shows the typed text. Prefix writes `https://` inside the value row in the placeholder color, so the person types only the part that varies. Suffix ends the row on a unit such as `kg`. ## Which states does Input have? Input has five states: Placeholder, Filled, Focused, Error and Disabled. Only the rule, the text and the icons move, so a form does not jump on error, and Focused adds a clear button before the trailing icon. Specimen: State. Placeholder, Filled, Focused, Error, Disabled. Focused is the brand rule alone: an underlined field has no box for a focus ring to follow, and the brand rule against the gray one is the cue a keyboard user needs. Error turns the rule, the hint and its icon red and keeps the typed value readable. Say what went wrong in the hint, because red is not a message. Every title row can carry (Optional) after the title and a Tooltip info icon at the far end. Both are Boolean properties and both are on by default, so turn them off on a field that is required or says everything in its label. ## Chip Input The same underlined field with a tag icon, for entries that become chips. Once there is a value, the chips sit in their own row between the rule and the hint. Specimen: Chip Input. field padding 8, gap 8, chip row 32 tall. Specimen: State Filled and Focused. ## Counter Input A pill with two round buttons and a number, for a quantity you nudge rather than type: the control iOS calls a stepper. The buttons work. Specimen: Counter Input. radius 9999, padding 6 and 12, buttons 32, value 18/28 Semi Bold. Specimen: State Focused, Error, Disabled. The pill strokes border/sub-200 at rest. Focused is a 1 pt brand stroke with the focus ring around the pill, and Disabled is a flat gray fill without a stroke. ## Digit Input One cell per digit, for a code that arrives by text message: 64 pt squares at radius 16 with a 30/36 Medium digit, so the number reads at arm's length. Type a code in it. Specimen: Digit Input. 64 x 64, radius 16, padding 16 and 8, 30/36 Medium. Specimen: State Focused, Error, Disabled. Focused is a 1 pt brand stroke plus the focus ring, and Error is a red stroke. Disabled is a gray fill without a stroke. ## Text Area The same underlined field, one line deep at first, grows by a line as you type up to five and then scrolls inside instead of pushing the form down. Type in it. Specimen: State Placeholder. 340 wide, 56 for one line, 24 more a line up to five, padding 16. Specimen: State Filled, Focused, Error, Disabled. The counter sits at the end of the hint row and follows the typing. Focused paints the rule in brand/base and Error in state/error/base-500, the same as Text Input. Use a Text Area for an answer longer than a sentence and a Text Input for everything else. ## Stepper Two buttons and a number, for a value you change by one, with no field and no label: the stepper sits in a row that already says what it counts. The buttons work. Specimen: Size md, State Default. sm 107 x 36, md 123 x 44, gap 12, value 16/24 Semi Bold. Specimen: Size sm, State Default, Min, Max. Min and Max change only the glyph of the button that would cross the bound, to fg/disabled-400. The button keeps its white fill and its stroke, so the other button still reads as live. The md size has 44 pt buttons and meets the iOS touch target. The sm size has 36 pt buttons, so give it a larger hit area in code. ## Composer A message or comment bar at one 40 pt height. Send stays dormant while the field is empty and turns brand blue as soon as there is text. Specimen: Style Default, live. 361 x 40, field 313 x 40, gap 8, avatar, action and send 40. Specimen: Style Default and Overlay, State Empty and Typing. The avatar, the action and the send circle share the 40 pt height with the field, so they line up without extra spacing. Avatar and Action are off by default and the paperclip accessory is on. Style Overlay draws the field and the action on translucent black and white with a blur, for a bar that floats over a photo or a video. Press Send in the live bar and it empties the field, as sending a message does. ## How does Input differ on iOS and Material 3? Appetite UI draws an underlined field with its own label and hint, 56 pt tall. iOS draws a bare 52 pt row and Material 3 draws a filled or outlined box, 56 dp tall. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | `Text Input` | `iOS / Text Field`, a 402 x 52 row with Placeholder, Focused, Typing and Value Entered | `M3 / Text Field`, 280 x 56, Filled or Outlined at radius 4, with Enabled, Focused, Error and Disabled | Appetite UI adds a label above, a hint below and an Error state that keeps the height. The platform fields carry no hint row. | | `Password`, `Prefix`, `Suffix` types | None in the file. SwiftUI uses SecureField for a password. | None in the file | The eye switch, the https:// prefix and the unit suffix are part of the Appetite UI field. | | `Counter Input`, `Stepper` | `iOS / Stepper`, a 92 x 32 pill | None in the file | Appetite UI Stepper is 107 x 36 at sm and 123 x 44 at md, so the md buttons meet the 44 pt target. | | `Digit Input` | None in the file. Set the one-time-code keyboard and autofill in code. | None in the file | Cells are 64 pt squares at radius 16. | | `Text Area`, `Chip Input`, `Composer` | None in the file | None in the file | These exist as Appetite UI components only. Chip Input draws its chips with the Chip component. | The minimum touch target comes from `platform/min-touch-target`, 44 pt on iOS and 48 dp on Android, and a 56 field row clears both. Read [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge) for the switch, and [iOS](https://www.appetiteui.com/docs/ios) and [Material 3](https://www.appetiteui.com/docs/material-3) for the platform mirrors. ## Properties Seven sets share one Figma page. Every property and its options, per set, read from the component definitions. | Property | Type | Options | Default | | --- | --- | --- | --- | | `Type` | Variant | Default, Left Selection, Right Selection, Password, Prefix, Suffix | Default | | `State` | Variant | Placeholder, Filled, Focused, Error, Disabled | Placeholder | | `Input Label`, `Optional`, `Tooltip`, `Help` | Boolean | on, off | on | | `Icon Left`, `Icon Right` | Boolean | on, off | on | | `Icon Left Swap`, `Icon Right Swap` | Instance swap | any icon | phone, chevron-down | | `Input Label Text`, `Input Text`, `Help Text` | Text | any string | Title of input, Placeholder text, This is a hint text to help user | | `Password Text`, `Prefix Text`, `Suffix Text` | Text | any string | ten dots, https://, kg | | Set | Property | Type | Options | Default | | --- | --- | --- | --- | --- | | Text Area | `State` | Variant | Placeholder, Filled, Focused, Error, Disabled | Placeholder | | Text Area | `Input Label`, `Optional`, `Tooltip`, `Help`, `Counter` | Boolean | on, off | on | | Text Area | `Input Label Text`, `Input Text`, `Help Text`, `Counter Text`, `Value Text` | Text | any string | Title of input, Add more detail, hint, 0/500, a sample sentence | | Chip Input | `State` | Variant | Placeholder, Filled, Focused, Error, Disabled | Placeholder | | Chip Input | `Input Label`, `Optional`, `Tooltip`, `Help`, `Icon Left` | Boolean | on, off | on | | Chip Input | `Input Label Text`, `Input Placeholder Text`, `Help Text` | Text | any string | Title of input, Add tags, hint | | Counter Input | `State` | Variant | Placeholder, Filled, Focused, Error, Disabled | Placeholder | | Counter Input | `Input Label`, `Optional`, `Tooltip`, `Help` | Boolean | on, off | on | | Counter Input | `Input Label Text`, `Input Number`, `Help Text` | Text | any string | Title of input, 24, hint | | Digit Input | `State` | Variant | Default, Focused, Filled, Disabled, Error | Default | | Set | Property | Type | Options | Default | | --- | --- | --- | --- | --- | | Stepper | `Size` | Variant | sm, md | sm | | Stepper | `State` | Variant | Default, Min, Max | Default | | Stepper | `Value` | Text | any string | 2 | | Composer | `Style` | Variant | Default, Overlay | Default | | Composer | `State` | Variant | Empty, Typing | Empty | | Composer | `Avatar`, `Action` | Boolean | on, off | off | | Composer | `Accessory` | Boolean | on, off | on | | Composer | `Placeholder`, `Value` | Text | any string | Message, Looks good to me | | Composer | `Action Icon`, `Accessory Icon` | Instance swap | any icon | camera, paperclip | Text Input 30 variants, Text Area 5, Chip Input 5, Counter Input 5, Digit Input 5, Stepper 6, Composer 4. Read from Figma on October 2, 2026. ## Tokens Every value the input reads, resolved through its aliases to the primitive underneath. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `border/sub-200` | #D1D1D6 | #48484A | The rule under the field, the Counter pill and the Digit cell | | `brand/base` | #155DFC | #2B7FFF | The rule while focused, the focused Counter and Digit stroke, the typing Send | | `state/error/base-500` | #FB2C36 | #FB2C36 | The rule, the stroke and the hint on error | | `text/soft-500` | #8E8E93 | #AEAEB2 | Label title, placeholder and affix text | | `fg/soft-500` | #8E8E93 | #AEAEB2 | Every icon at rest | | `text/strong-950` | #0E0E0F | #FFFFFF | The typed value, the Counter label and the Stepper value | | `text/sub-700` | #48484A | #C7C7CC | Hint text | | `text/disabled-400` | #AEAEB2 | #8E8E93 | Value and hint when disabled, and (Optional) | | `border/soft-100` | #E9E9EA | #2F2F31 | Selection divider, Counter and Stepper buttons | | `bg/white-0` | #FFFFFF | #0E0E0F | Counter, Digit and button fills | | `bg/weak-50` | #F4F5F5 | #242427 | Composer field, disabled Counter and Digit fill | | `bg/soft-100` | #E9E9EA | #48484A | The dormant Send | | `fg/sub-700` | #48484A | #C7C7CC | The Stepper glyphs | | `fg/disabled-400` | #AEAEB2 | #8E8E93 | Icons when disabled, the Stepper glyph at a bound and the dormant Send arrow | | `text/on-color/strong` | #FFFFFF | #FFFFFF | The Send arrow while typing | | `static/static-white-0` | #FFFFFF | #FFFFFF | The Overlay value and glyphs | The Overlay Composer uses the primitives `colors/alpha/black/alpha-24`, `colors/alpha/white/alpha-24` and, for the placeholder, `colors/alpha/white/alpha-72`, which do not change between Light and Dark, with `backdropBlur/sm`. Counter and Digit Focused use the effect style `focusRing/brand`: a 2 pt gap in the surface color, then a 2 pt brand ring. ## Guidelines - Do: Keep the hint slot filled from the start and swap its text on error. The field never changes height, so the form does not jump. - Avoid: Do not signal the error with the red rule alone. A color blind user cannot read the rule, so the message has to say what is wrong. Keep fields at 16 pt text or larger so iOS does not zoom the page on focus. Name every field with its label, because the placeholder disappears as soon as someone types. The label title, the placeholder and the affix text use text/soft-500, #8E8E93, which measures 3.26 to 1 on white in Light. Give the real field a color at 4.5 to 1 for text a person has to read. For keyboard focus the real field shows the brand rule, and Counter and Digit add the 2 plus 2 focus ring. Composer is 40 pt high, so give it a 44 pt hit area in code. --- --- title: List description: List shows related items as rows with a leading visual, text and a trailing control. Appetite UI Figma component: two sizes, four trailings, swipe actions. group: Components source: https://www.appetiteui.com/docs/list dateModified: 2026-10-03 --- # List Updated: October 3, 2026. List shows related items as rows, each with a leading visual, text and one trailing control. ## Preview One row of a scrollable list, where the trailing is the promise: a chevron opens a screen, a toggle flips something now, a radio picks one of several, a value only reports. Choose it before the label. Specimen: List, Trailing Chevron, State Default. 340 x 76, radius 24, padding 16, gap 12. The width is fixed at 340 and the height hugs: 16 of padding, a 24 line over a 20 line, 16 of padding, so 76. The row clears the 44 pt target on iOS and the 48 dp one on Android. Source: the List set of the Appetite UI Figma file, read on October 2, 2026. ## How tall is a List row? Default is a two line row with a tile, 76 high. Compact is a one line row at 48 high, for menus and settings where the supporting line would repeat the label. Specimen: Size Default, Size Compact. 340 x 76 and 340 x 48, radius 24, padding 16 and 12 over 16. Compact drops the 40 tile for a bare icon at 20 in a 24 box, pads 12 over 16 and carries the label only, with Description off in every Compact variant. The rows are 76 and 48 high at the same 340 width and the same radius 24, so the two sizes can sit in one list. The Platform collection sets `platform/list-row/min-height` to 44 on iOS and 56 on Android. Compact at 48 clears the iOS minimum and sits under the Android one, so on Android use Default or pad the row in code. The Toggle and Radio keep their size, so they overflow the 24 of content height evenly and the row stays 48. Compact comes in all four trailings and all three states, half of the 24 variants of the set. ## What can lead a List row? The leading slot holds a tile with an icon, or an Avatar when the row is about a person. A bare icon replaces the tile at Compact. Specimen: Leading Icon, Leading Avatar. tile 40 at radius 12, icon 20, Avatar 40 and 24. Leading Avatar puts an Avatar where the tile sits, xl (40) at Default and base (24) at Compact; it ships off, so turn it on and turn Leading Icon off. A disabled row dims the avatar to 40 percent. The icon sits in a 20 box at stroke 1.75 on state/faded/base-500, and the tile is state/faded/lighter-50 at radius 12. ## Which trailings does List have? List has four trailings on one axis: chevron, text, toggle and radio. The chevron is a 20 glyph, the text a 14/20 value, and the toggle and the radio sit in 44 targets, so the row stays 76 tall either way. Specimen: Chevron, Text, Toggle, Radio. 20 chevron, 14/20 value, 44 x 28 track, 22 disc. Chevron sits on text/soft-500, Text on text/sub-700, and Toggle and Radio on brand/base. The Toggle ships on and the Radio ships selected in every variant, so drive both from your own data. Text reports a value chosen somewhere else and never takes a tap. The Radio disc is 22 with a 10 dot, and the chevron is stroke 1.75. ## Which states does List have? Three states across all four trailings: Pressed lays a gray Highlight inside the row and Disabled moves the ink. Nothing resizes or shifts. Specimen: Default, Pressed, Disabled. Highlight inset 4, bg/weak-50, tile bg/white-0. Pressed lays a bg/weak-50 Highlight inside the row, inset 4 on every side, rounded like the row (a capsule on Compact) and under the content. The leading tile turns bg/white-0 so it stays visible on the gray, and a press never reaches the control, so the toggle keeps its paint. Disabled moves all ink to text/disabled-400 and fg/disabled-400, dims an avatar to 40 percent and takes the Toggle track to 40 percent of brand/base. There is no Hover state. The Highlight is an absolute layer named Highlight inside each Pressed variant. ## How do swipe actions work? A private set, _List Row - Swipe Actions: the row lifts onto bg/weak-50 and slides by the width of its actions, which wait beside it as round buttons with a label under each. One to three per side. Specimen: Side Trailing, Actions 3, then Side Leading, Actions 2. actions 60 x 68, circle 48, glyph 22, label 12/16 at gap 4. The actions are 48 circles with a 12/16 Semi Bold label below, 4 apart. Pin is brand/base, Read state/success/base-500, Flag state/away/base-500 and Delete state/error/base-500. Trailing carries Archive, Flag and Delete, with the destructive one at the edge. Leading carries Pin and Read, and Archive as a third. Every action must also exist somewhere a user can find it, because a swipe teaches nobody it is there. Archive sits on bg/surface-800, which inverts in dark to #D1D1D6 while its glyph stays white. The swipe set has its own axes, Side and Actions, 6 variants. ## What is Price Row? Price Row is a separate set for itemized totals: a label on the left and a value on the right, at two emphases. Specimen: Emphasis Default, Emphasis Strong. 345 x 20 and 345 x 24. Default sets both lines at 14/20, the label on text/sub-700 and the value on text/strong-950. Strong sets both at 16/24 Semi Bold on text/strong-950, for the total. Price Row stands apart from the List rows: it has no tile, no trailing and no State, and it is 345 wide where List is 340. Price Row holds 2 variants. ## Properties Three variant axes and seven instance properties on List. The swipe set and Price Row have their own. | Set | Property | Type | Default | | --- | --- | --- | --- | | List | `Size` | Default \| Compact | Default | | List | `Trailing` | Chevron \| Toggle \| Radio \| Text | Chevron | | List | `State` | Default \| Pressed \| Disabled | Default | | List | `Leading Icon` | Boolean | true | | List | `Icon Swap` | Instance swap | bell | | List | `Leading Avatar` | Boolean | false | | List | `Description` | Boolean | true | | List | `Label` | Text | List item | | List | `Supporting Text` | Text | Description | | List | `Trailing Text` | Text | English | | _List Row - Swipe Actions | `Side` | Trailing \| Leading | Trailing | | _List Row - Swipe Actions | `Actions` | 1 \| 2 \| 3 | 1 | | Price Row | `Emphasis` | Default \| Strong | Default | | Price Row | `Label` | Text | Service fee | | Price Row | `Value` | Text | $68 | Description off leaves one 24 line in the column. Leading Icon off hands back its 40 and the 12 gap. List holds 24 variants, which is Size, Trailing and State crossed. ## Tokens Every value the row reads, resolved to its primitive. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/white-0` | #FFFFFF | #0E0E0F | Row, and the tile while Pressed | | `bg/weak-50` | #F4F5F5 | #242427 | Pressed Highlight and the lifted swipe row | | `state/faded/lighter-50` | #F4F5F5 | #6A7282 at 16% | Leading tile | | `state/faded/base-500` | #8E8E93 | #636366 | Leading icon | | `text/strong-950` | #0E0E0F | #FFFFFF | Label and Price Row value | | `text/sub-700` | #48484A | #C7C7CC | Supporting line, value and swipe label | | `text/soft-500` | #8E8E93 | #AEAEB2 | Chevron | | `text/disabled-400` | #AEAEB2 | #8E8E93 | Disabled ink, with fg/disabled-400 | | `brand/base` | #155DFC | #2B7FFF | Toggle track, Radio disc, Pin | | `icon/on-color` | #FFFFFF | #FFFFFF | Radio dot | | `bg/soft-100` | #E9E9EA | #48484A | Disabled Radio disc | | `static/static-white-0` | #FFFFFF | #FFFFFF | Toggle handle | | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `state/error/base-500` | #FB2C36 | #FB2C36 | Delete, one value both modes | | `state/away/base-500` | #FE9A00 | #E17100 | Flag | | `state/success/base-500` | #22C55E | #16A34A | Read | | `bg/surface-800` | #2F2F31 | #D1D1D6 | Archive, inverts in dark | | `text/on-color/strong` | #FFFFFF | #FFFFFF | Action glyph | Radius 24 is `dimensions/radius/2xl` and the tile 12 is `dimensions/radius/lg`, and the icons carry stroke 1.75. The bell is `state/faded/base-500` and the chevron `text/soft-500`, two grays that part company in dark. The chevron reads `text/soft-500`, 3.26 to 1 on white, and disabled ink is #AEAEB2 at 2.21 to 1, which WCAG exempts on a disabled row. In code each row is one focusable control with a visible focus ring, and the Toggle and Radio sit in 44 targets. ## How does List differ on iOS and Material 3? Both platforms have a list. iOS draws a full width table in three styles and Material 3 a 56 high item with up to three lines. Appetite UI List is a card shaped row on both. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | List | iOS / List in Plain, Grouped and Inset Grouped, built from _List Row at Regular 52 or Tall, with eleven trailing kinds | M3 / List Item in One, Two and Three lines, with or without a leading element, 360 x 56 | Appetite UI rows are 340 wide at radius 24 and stand alone, where iOS rows are 52 high inside a table and Material rows are flush with the screen edge. Appetite UI has four trailings against eleven on iOS. | Apple and Material set the row height by platform. In Appetite UI the Default row is 76 and Compact 48, both clear of `platform/min-touch-target`, 44 pt on iOS and 48 dp on Android, and Compact sits under the 56 Android row of `platform/list-row/min-height`. ## Which trailing should I use? Match the trailing to what the tap does: a chevron opens a screen, a toggle flips something now, a radio picks one of several, and a value only reports. - Do: Match the trailing to what the tap does. A chevron promises a screen, so the supporting line can summarize it. - Avoid: Do not put a toggle on a row that also opens a screen. Two targets, and the bigger one wins the thumb. Keep the label to one line. The content column is 224 with the leading tile on, about thirty characters at 16 Semi Bold, and a row that wraps grows past 76. --- --- title: Modal description: Modal interrupts the screen for one decision that must come first. Appetite UI Figma component: a centered Modal and a bottom Modal Sheet at radius 40. group: Components source: https://www.appetiteui.com/docs/modal dateModified: 2026-10-03 --- # Modal Updated: October 3, 2026. Modal interrupts the screen with a decision that has to be made before anything else continues. ## Preview A dialog that interrupts and asks for a decision. One primary action, one secondary, a close. If the answer can wait, or there is no decision, this is the wrong component. Specimen: Modal, Title and Slot. 340 x 344, radius 40, padding 24 20 20. Three parts sit at gap 16: a 32 title row, the 140 slot and a 96 button column. The height hugs inside 24 of top padding and 20 at the sides and the bottom. The title fills the row, and the 32 close button takes what it needs. The Modal is a centered dialog at radius 40 on all four corners, with dropShadow/2xl under it. It fills bg/raised, white in Light and #242427 in Dark, so a dark dialog lifts off a #0E0E0F screen without a stroke. The close is a 32 Compact Button, under the minimum touch target. Give it a 44 pt hit area on iOS and 48 dp on Android in code. Source: Modal, node 209:1676 of the Appetite UI Figma file, read on October 2, 2026. ## What goes in the Modal slot? Anything the decision needs, such as a line of copy, a list, a form or a preview. The middle block is a native Figma slot with no fill and no content of its own, and it is the only part a decision changes. Specimen: Slot filled with copy. 300 x 140, buttons 44 at gap 8. The slot is 300 x 140 and pads its content 12 at gap 8. The pink dashes mark an empty slot in these docs, and the component does not ship them. The buttons are a Brand Filled and a Brand Link at md, stacked, so a long label never truncates. ## When should I use Modal Sheet? Use the sheet for a focused sub-task, such as a secondary flow or a picker. It is a separate component: a page sheet on iOS and a full-screen dialog on Android. Specimen: Modal Sheet, Title, Subheadline and Slot. 393 x 789, radius 40 40 0 0, back sheet 345 x 10. The sheet is drawn at full size, 393 wide and 789 high. A back sheet 345 wide peeks 10 above the front one, inset 24 on each side in bg/soft-100, so a sheet that opens another reads as a stack. The front sheet is radius 40 on its top corners, with a 48 x 5 drag handle, a header with a title, a close and a subheadline, a 496 tall slot, and two lg buttons. The ground in the specimen is the screen under bg/scrim. The sheet is bg/white-0 and fully opaque, and the screen blurs behind it through backdropBlur/md. Source: Modal Sheet, node 244:4922 of the Appetite UI Figma file, read on October 2, 2026. ## Properties Neither component is a variant set. Modal has two properties and Modal Sheet has four. | Component | Property | Type | Default | | --- | --- | --- | --- | | Modal | `Title` | Text | Title of modal | | Modal | `Content Slot` | Slot | empty, 300 x 140 | | Modal Sheet | `Title` | Text | Title of sheet | | Modal Sheet | `Subheadline` | Boolean | true | | Modal Sheet | `Subheadline Text` | Text | Subheadline of sheet | | Modal Sheet | `Content Slot` | Slot | empty, 353 x 496 | The two buttons are Button instances with their own properties. A destructive dialog swaps the first to Type Error on the instance. The close is a Compact Button at Style Transparent. A decision-free message belongs in a Toast or an Alert. ## Tokens Every value the two components read, resolved to its primitive. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/raised` | #FFFFFF | #242427 | Modal surface | | `bg/white-0` | #FFFFFF | #0E0E0F | Modal Sheet front | | `bg/soft-100` | #E9E9EA | #48484A | Modal Sheet back sheet | | `border/sub-200` | #D1D1D6 | #48484A | Drag handle | | `text/strong-950` | #0E0E0F | #FFFFFF | Titles | | `text/sub-700` | #48484A | #C7C7CC | Subheadline | | `fg/soft-500` | #8E8E93 | #AEAEB2 | Close glyph | | `brand/base` | #155DFC | #2B7FFF | Filled button, link label | | `static/static-white-0` | #FFFFFF | #FFFFFF | Filled button label | Radius 40 is `dimensions/radius/4xl`. The Modal casts `dropShadow/2xl`, the same shadow as the Action Sheet, and the Modal Sheet's fill effect is `backdropBlur/md`. Padding runs on `spacing/6` 24, `spacing/5` 20, `spacing/4` 16 and `spacing/2` 8. ## How does Modal differ on iOS and Material 3? Both platforms split the job in two: a centered dialog for a decision and a sheet for a flow. Appetite UI Modal and Modal Sheet are the two halves, one pair for both platforms. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Modal | iOS / Alert, the centered decision in the Apple Platform pages | M3 / Basic dialog, 304 x 240 at radius 24, plus List dialog and Scrollable list dialog | Appetite UI Modal is 340 wide at radius 40 with a slot and stacked buttons. Material dialogs are narrower and put text buttons on one row. | | Modal Sheet | iOS / Sheet - Full Screen in Medium, Large and Large (Stacked) detents, iOS / Sheet - Inspector and iOS / Sheet - Duo | M3 / Bottom sheet, Modal False or True, 412 wide, and M3 / Side Sheet | Appetite UI draws one 393 wide sheet with a stack peek. iOS has real detents and Material has a standard and a modal bottom sheet. | Detents and drag behavior belong to the platform. Build the sheet with the native control, a page sheet on iOS and a full-screen dialog on Android, and take the surface, the handle and the actions from Appetite UI. The minimum touch target is 44 pt on iOS and 48 dp on Android, set by `platform/min-touch-target`. ## Guidelines - Do: Put the decision in the title and the verb on the button. Discard and Keep editing say what happens; OK and Cancel make the user re-read the title. - Avoid: Do not ask a question the buttons cannot answer. Sure about what, and what does OK agree to? Show one modal at a time and never open one from another. The close button and the secondary action do the same job here, so give the secondary a real label instead of a second dismiss. Use Modal Sheet when the content is a list or a picker: a sheet is easier to reach with a thumb and easier to leave. --- --- title: Navigation description: Navigation is the bottom tab bar that moves people between the main sections of an app: two to five tabs in a floating pill. Component for iOS and Android. group: Components source: https://www.appetiteui.com/docs/navigation dateModified: 2026-10-03 --- # Navigation Updated: October 3, 2026. Navigation is the bottom bar that moves people between the main sections of an app. Two to five destinations in a floating pill, one of them active. ## Preview The bottom tab bar, and the only persistent navigation in the app. Two to five destinations, always the same set, always in the same order. If a destination comes and goes, it does not belong here. The specimen is live, so pick one. Specimen: Navigation, Tabs 2. 340 x 62, pill, padding 2, inner row 336 x 58, pill 168. The bar is a pill, not a strip across the bottom of the screen. A 1px stroke is drawn outside it, so it costs no size, and under it sits `dropShadow/lg`, two shadows that lift the pill off whatever it floats over. The icon is 24 and the label 12/16 Semi Bold, and the two measure 44 with their gap, centered in the 58. The active destination is the pill, a wash at radius full behind its icon and label. The file gives the switch no motion, so in the kit it changes on the tap; the stage above slides it. ## How many tabs can Navigation hold? Two to five, on one axis, and nothing changes but the arithmetic. The bar stays 340 by 62 and each destination takes an equal share of the 336 inside it. Specimen: Tabs 2, 3, 4 and 5. 168, 112, 84 and 67.2 per destination. Five is a real ceiling: 67.2 leaves about eight characters at 12 Semi Bold before the label truncates. At two, a [Segmented Control](https://www.appetiteui.com/docs/segmented-control) is usually the better answer, since a bar that only ever holds two destinations spends the whole bottom of the screen on one choice. ## Active and badge The label behind every destination is a private component with one axis and three properties. Active is a fill and two colors. Badge is a dot. Specimen: Active False, Active True, Badge on both. pill on alpha-10, brand icon and label, 6 dot. The dot sits flush with the icon's top right corner, so it never widens the destination. It carries no count and says only that something is waiting. It is the Badge component at Type Dot. The label component ships with Badge true, and all four published bar variants set it false. ## How does Navigation differ on iOS and Material 3? Appetite UI Navigation is a floating pill like the iOS tab bar. Material 3 draws a full width bar at 80 high with a different item count. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Navigation, 340 x 62 pill, Tabs 2 to 5 | iOS / Tab Bar, a floating capsule 62 high, two to five tabs | M3 / Navigation bar, 412 x 80, three to five items | Material is a full width bar with a separate 24 high Gesture Navigation component. Appetite UI and iOS float on the content, and Appetite UI allows two tabs where Material starts at three | | Active pill, brand label and icon | Selected tab on a capsule fill | Active indicator behind the icon | Appetite UI draws the pill behind both icon and label | The minimum touch target is 44 on iOS and 48 on Android, from `platform/min-touch-target`. A destination is 58 high and at least 67.2 wide, so every tab clears both. See [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge) and the [Material 3 page](https://www.appetiteui.com/docs/material-3). ## Properties One axis on the published bar. Everything else lives on the private label inside it. | Property | Type | Default | | --- | --- | --- | | `Tabs` | 2 \| 3 \| 4 \| 5 | 2 | | `Active` | False \| True, on the label | False | | `Label` | Text, on the label | Title | | `Icon Swap` | Instance swap, on the label | circle | | `Badge` | Boolean, on the label | true | The bar has four variants and the label two. Set Active on exactly one destination: the component lets you light two, and a bar with two active tabs tells nobody where they are. There is no Disabled and no Pressed on the bar, so a destination that is unavailable should not be in it at all. ## Tokens Every value the bar and its labels read, resolved to their primitive. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/white-0` | #FFFFFF | #0E0E0F | Bar surface | | `border/soft-100` | #E9E9EA | #2F2F31 | 1px outside stroke | | `brand/base` | #155DFC | #2B7FFF | Active icon and label | | `text/soft-500` | #8E8E93 | #AEAEB2 | Inactive label | | `fg/soft-500` | #8E8E93 | #AEAEB2 | Inactive icon | | `state/error/base-500` | #FB2C36 | #FB2C36 | Badge dot | | `colors/alpha/gray/alpha-10` | #6A7282 at 10% | #6A7282 at 10% | Active pill, one value both modes | The active pill is a single mode value, so it stays #6A7282 at 10 percent in dark, a faint light wash on a #0E0E0F bar. The icon and label carry the state as well, and the pill is the signal that reads first. In light mode an inactive label is #8E8E93 on white, a contrast of 3.26:1 and a documented product choice, under the 4.5:1 that WCAG asks of small text. Keep labels short and let the icon say the rest. In code, give each tab a visible focus ring, mark the active one as current for VoiceOver and TalkBack, and describe the badge dot in words, since the dot carries no text. Geometry runs on `dimensions/radius/full`, `dimensions/spacing/0-5` 2 around the row, `dimensions/spacing/1-5` 6 above and below each destination and `dimensions/spacing/1` 4 between icon and label. The shadows are the effect styles `dropShadow/lg` on the bar and `dropShadow/xs` on the dot. ## Guidelines - Do: Name the place, not the action. A tab bar switches destinations, so Home, Search and Inbox are nouns a user can point at. - Avoid: Do not put a verb in the bar, and do not write a label the width cannot hold. Create new document is an action, and it truncates. Keep the set fixed. A tab that appears only sometimes teaches the user that the bottom of the screen cannot be trusted, and the value of a persistent bar is that the same thing is always in the same place. If the destination count changes with the account type, pick the larger set and disable nothing, or build the smaller product a smaller bar. --- --- title: Pagination description: Pagination shows how many pages there are and which one is current, as three dots or as numbers. Appetite UI component for Figma, iOS and Android. group: Components source: https://www.appetiteui.com/docs/pagination dateModified: 2026-10-03 --- # Pagination Updated: October 3, 2026. Pagination shows how many pages or slides there are, and which one someone is on. Dots report a swipe, numbers let people jump. ## Preview Where you are in a paged sequence. Dots for carousels and onboarding, Numbered for lists and tables. On mobile, prefer scrolling wherever the content allows. Specimen: Pagination, Style Numbered, Active Center. 356 x 36, nine 36 targets at gap 4. Every width here is arithmetic: nine 36 targets and eight 4 gaps make 356, seven targets make 276. 356 does not fit a 390 screen once you add a page margin. ## When should I use Pagination dots? Use dots where the user swipes and the indicator only reports: a carousel or onboarding. Three dots, 26 by 24, and the only thing that moves is which one is big. Specimen: Active First, Center, Last. current 8 on brand/base, the others 5, gap 4. Three is what the component ships, and the idea holds to about six dots, past which they stop being countable. The current dot is 8 and the others 5, so size carries the state as well as color, readable without telling blue from gray. The inactive dots are one value in both modes, so they do not lift in dark. ## Numbered Two arrows and a run of numbers with the middle truncated. The three variants are three positions in the sequence, each truncating differently. Specimen: Active First, Center, Last. 276, 356 and 276, arrows disabled at the ends. First disables the back arrow, Last the forward one, Center enables both and pays with two ellipses. The ellipsis is the Disabled state of the same 36 target and looks pressable, so give it no tap handler. The numbers are placeholders in the file. ## Which states does a page number have? Four, on the private target behind every number: Default and Pressed on a rounded square, Active on the brand circle, and the ellipsis. Specimen: Default, Pressed, Active, Disabled. 36 x 36, 14/20 at ls .1, radius 16 or full. Default and Pressed targets are a rounded square at radius 16. Active is the only state drawn as a full circle. Default has no fill, Pressed takes `bg/weak-50`, Active takes `brand/base` and turns the label Semi Bold, Disabled is the ellipsis. Active is the only state that changes the weight. The chevrons are their own component with one boolean and no pressed state. ## How does Pagination differ on iOS and Material 3? iOS has a page control of dots and no numbered pager. The Material 3 pages in the file have no pagination component at all. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Pagination, Style Dots | iOS / Page Control, dots only, at Pages 3, 5 and 8 | No counterpart | Same job: report the position in a swipe. Appetite UI sizes the current dot 8 and the others 5 | | Pagination, Style Numbered, 36 targets | No counterpart | No counterpart | Neither platform ships a numbered pager, so this one is Appetite UI's own | Dots only report, so no touch target applies. In code, build them as the page indicator of a TabView on iOS and a HorizontalPager indicator on Android. A Numbered target is 36, under the 44 minimum on iOS and the 48 on Android from `platform/min-touch-target`. Keep the drawn target at 36 and extend each hit area to 44 or 48 in code, or use Dots, a Load more button or plain scrolling where the user does not need to jump. See [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge). ## Properties Two axes on the published component, six variants. The three private blocks behind it carry their own. | Property | Type | Default | | --- | --- | --- | | `Style` | Dots \| Numbered | Dots | | `Active` | First \| Center \| Last | First | | `State` | Active \| Default \| Pressed \| Disabled, on _Page | Default | | `Disabled` | False \| True, on _Chevron | False | | `Active`, `Background` | True \| False, Dark \| Light, on _Dot | False, Light | There are no text properties: the numbers are baked into each variant, so real page numbers mean overriding the text on each instance. The widths do not change. A 36 target holds two digits comfortably and three at a squeeze. ## Tokens Every value the component reads, resolved to its primitive. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `brand/base` | #155DFC | #2B7FFF | Active page, active dot | | `text/on-color/strong` | #FFFFFF | #FFFFFF | Active page label, one value both modes | | `bg/weak-50` | #F4F5F5 | #242427 | Pressed page | | `text/strong-950` | #0E0E0F | #FFFFFF | Every other page number | | `text/disabled-400` | #AEAEB2 | #8E8E93 | Ellipsis | | `fg/sub-700` | #48484A | #C7C7CC | Enabled chevron | | `fg/disabled-400` | #AEAEB2 | #8E8E93 | Disabled chevron | | `colors/alpha/gray/alpha-16` | #6A7282 at 16% | #6A7282 at 16% | Inactive dot, one value both modes | The inactive dot is a single mode Foundations primitive, so it does not theme. A page runs on `dimensions/radius/xl` 16 at Default and Pressed and on `dimensions/radius/full` at Active. ## Guidelines - Do: Use Dots where the user swipes and the indicator only reports. Nothing to press, nothing to read, and it survives any width. - Avoid: Do not put nine 36 targets across a phone. On mobile the default is to skip pagination. Infinite scroll or a Load more button beats a row of small round targets. Reach for Numbered when the user needs to jump to a page. If they only ever go forward, one arrow and a count is the whole control. --- --- title: Picker description: Date, Time and Color Picker in Figma: a calendar with range states, a time slot list with quick durations, and a color spectrum with the product palette. group: Components source: https://www.appetiteui.com/docs/picker dateModified: 2026-10-03 --- # Picker Updated: October 3, 2026. Picker lets people choose a date or a range of dates, a time, or a color, in three cards that share one surface. ## Preview A calendar grid for one date. Use it when the shape of the month matters and a scrolling wheel would hide it. Pick a day, then Submit to keep it or Dismiss to go back. Specimen: Date Picker, no properties. 340 x 400, radius 32, padding 20, dropShadow/2xl. The card shows January 2026 with the 16th selected and the 2nd, 12th, 17th and a spilled 3rd marked. Seven 36 cells and six 8 gaps fill the 300 that the padding leaves. Monday takes one letter, the other six take two. The card is bg/raised under dropShadow/2xl, with no stroke. ## What does the Date selector do? The month header is its own private component and the only control in the card that changes what the grid shows. Specimen: Date Selector. 300 x 44, padding 6, gap 8, radius full. The selector is a bg/weak-50 pill holding two 32 Compact Buttons at Style White, with the month label centered between them. ## Which states does the Day cell have? The Day cell has eight states crossed with one boolean, and every one is a 36 pt circle. It is the private target behind every number. Specimen: Default, Pressed, Active, Disabled. 36 circle, 14/20 Semi Bold at ls .1. Today marks the current date. Range Start, Range Middle and Range End draw one band across the 8 pt gap between days. Specimen: The same four with Marked. 4 dot, centered, 5 up from the bottom. Specimen: Today, with and without Marked. 36 circle, number on brand/base, dot 4. Specimen: Range Start, Range Middle, Range End. 36 circle, range band 22 and 44 wide. Default has no fill and the number on text/sub-700. Pressed takes bg/weak-50 and lifts the number to text/strong-950. Active is brand/base under a static white number. Today keeps the clear cell and sets the number in brand/base. Disabled is a spilled day from the next month. Range Start and Range End are a brand circle with a half band toward the middle, and Range Middle is the band alone, with the number on text/strong-950. The band is 22 wide at the ends and 44 wide in the middle, and it reaches 4 pt past the cell on every side it joins, so a run of cells reads as one band across the 8 pt gap between days. The band is brand/alpha-10: 10 percent of the brand blue in both modes. The dot is absolutely placed, so it never moves the number. ## How does the Time Picker work? A list of time slots with three quick durations, in a card like the Date Picker's, at radius 40. Pick a slot, then Submit to keep it. Specimen: Time Picker, Format 12-hour. 340 x 426, radius 40, padding 20, gap 16. Specimen: Time Picker, Format 24-hour. 340 x 426, radius 40, padding 20, gap 16. The header pill shows the picked time, with a clock on the left and a clear button on the right. Below it, three quick durations sit in a row: the chosen one is a brand tinted pill with a check. The list holds half hour slots from 09:30, and its 4 pt scrollbar shows how much is left. The picked slot is bg/weak-50 with a brand tick. Format only changes the list: in 12-hour each slot adds AM or PM, and in 24-hour the period disappears. The arrow keys move through the durations and the slots, Dismiss puts the pick back on 10:30 and Submit keeps the slot you chose. ## How does the Color Picker work? A free color from the spectrum, or a pick from the product palette, in a card like the Date Picker's, at radius 40. Drag the spectrum, type a hex value or choose a swatch. Specimen: Color Picker, Type Custom. 340 x 434, radius 40, spectrum 300 x 148, hue 16 tall. Specimen: Color Picker, Type Palette. 340 x 326, radius 40, three rows of seven swatches at 32. A small two tab [Segmented Control](https://www.appetiteui.com/docs/segmented-control), Custom and Palette, heads both types. Custom has a spectrum, a hue slider, a value row with an eyedropper and a hex field, and a row of saved swatches with an Add button. Palette has three rows of seven swatches, and the value row follows the picked swatch. The swatches are the product's own state colors, so the palette changes with Light and Dark: the light shades of each color are translucent in Dark, and the opacity field shows it. The spectrum is saturation across and brightness down on the hue you set with the slider. Both handles are sliders for the keyboard: the arrow keys move them, Shift moves ten times as far, and Home and End jump the hue to its ends. The hex field takes six digits with or without the hash. ## How does Picker differ on iOS and Material 3? iOS draws date and time in one inline or compact picker, Material 3 splits them into modal, input, dial and keyboard pickers, and neither has a color picker in the file. Appetite UI draws three 340 wide cards. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | `Date Picker`, 340 x 400, radius 32 | `iOS / Date and time - Pickers`, Compact 370 x 381 and Inline 370 x 388 | `M3 / Modal date picker`, 360 x 524 at radius 24, with Day, Year and Full-screen (range) | Appetite UI adds Today and a range band to the day cell and drops the year grid. | | `Time Picker`, 340 x 426, radius 40 | The time wheel inside `iOS / Date and time - Pickers` | `M3 / Dial picker`, 328 x 520, and `M3 / Keyboard picker`, 328 x 243 | Appetite UI picks from a list of slots with quick durations instead of a wheel or a dial. | | `Color Picker`, 340 x 434 and 340 x 326 | None in the file. SwiftUI has a native ColorPicker. | None in the file | Appetite UI draws its own spectrum and a palette of the product's state colors. | In code, build the Date Picker as a DatePicker with the graphical style on iOS and a DatePicker on Android. For a compact inline choice, use the date selector instead. The minimum touch target comes from `platform/min-touch-target`: 44 pt on iOS and 48 dp on Android. The day cells, the slots and the swatches are 36, 36 and 32 pt, below both, so in code give each target the platform minimum around the drawn shape. Read [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge) for how one screen switches between the platforms, and [iOS](https://www.appetiteui.com/docs/ios) and [Material 3](https://www.appetiteui.com/docs/material-3) for the platform mirrors. ## Properties The Date Picker has no properties of its own, the Time Picker has Format and the Color Picker has Type. Every other knob lives on a private block inside them. | Component | Property | Type | Options | Default | | --- | --- | --- | --- | --- | | Date Picker | none | none | none | 340 x 400 | | Time Picker | `Format` | Variant | 12-hour, 24-hour | 12-hour | | Color Picker | `Type` | Variant | Custom, Palette | Custom | | _Day Cell | `State` | Variant | Default, Active, Disabled, Pressed, Today, Range Start, Range Middle, Range End | Default | | _Day Cell | `Marked` | Variant | False, True | False | | _Day Cell | `Type` | Variant | Basic | Basic | | _Day Cell | `Date` | Text | any string | 1 | | _Day Label | `Text` | Text | any string | M | | _Date Selector | `Edit Date` | Text | any string | June 2026 | | _Time Picker Item | `State` | Variant | Default, Active | Default | | _Time Picker Item | `Show Period` | Boolean | on, off | on | | _Time Picker Item | `Time`, `Period` | Text | any string | 10:30, AM | | _Duration Chip | `State` | Variant | Default, Selected | Default | | _Duration Chip | `Label` | Text | any string | 30 min | | _Color Swatch | `State` | Variant | Default, Selected | Default | _Day Cell 16 variants, Time Picker 2, Color Picker 2. Source: the Picker page of the Appetite UI Figma file, read on October 2, 2026. ## Tokens Every value the pickers read, resolved to its primitive. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/raised` | #FFFFFF | #242427 | All three cards, and the duration chips | | `bg/white-0` | #FFFFFF | #0E0E0F | Caret buttons, header buttons, value field, Dismiss | | `border/soft-100` | #E9E9EA | #2F2F31 | Duration chip edge and the Dismiss outline | | `bg/weak-50` | #F4F5F5 | #242427 | Selector, header and value pills, the pressed cell, the picked slot, scrollbar track | | `bg/sub-200` | #D1D1D6 | #636366 | Scrollbar thumb | | `text/sub-700` | #48484A | #C7C7CC | Month label, day numbers, slot times, chip labels | | `text/soft-500` | #8E8E93 | #AEAEB2 | Day labels, AM and PM, the opacity | | `text/strong-950` | #0E0E0F | #FFFFFF | Pressed cell number, picked slot, hex value | | `text/disabled-400` | #AEAEB2 | #8E8E93 | Spilled days, with fg/disabled-400 on their dot | | `fg/sub-700` | #48484A | #C7C7CC | Carets and header icons | | `brand/base` | #155DFC | #2B7FFF | Selected cell, Today, range ends, ticks, Submit | | `brand/alpha-10` | #2B7FFF at 10 percent | #2B7FFF at 10 percent | Range band, chosen duration | | `border/strong-950` | #0E0E0F | #FFFFFF | The ring on the picked swatch | | `brand/lighter` | #EFF6FF | #132150 | The dot inside a selected cell | | `static/static-white-0` | #FFFFFF | #FFFFFF | Selected cell number, Submit label, spectrum ring | The palette swatches read the state tokens: `state/error`, `state/warning`, `state/away`, `state/success`, `state/stable`, `state/feature`, `state/highlighted`, `state/verified` and `state/faded` at base 500, their light 200 shades, and `brand/base`. Geometry runs on `dimensions/radius/3xl` 32 for the Date Picker card and `dimensions/radius/4xl` 40 for the Time and Color Picker cards, with all three on `dropShadow/2xl`. Day labels, AM and PM and the opacity read `text/soft-500`, which measures 3.26:1 on white and is a documented product choice. In code the calendar is a grid whose cells take arrow-key focus with a visible ring, and every target needs the 44 pt iOS or 48 dp Android minimum. ## When should I use the calendar? Use the calendar when the shape of the month is part of the decision: a weekend, a deadline near the end, a run of marked days. - Do: Use Range Start, Range Middle and Range End for a span of dates. The band joins the cells into one shape and the two ends carry the only brand circles. - Avoid: Do not fill a run of cells with Active to fake a range. Three brand circles read as three selections, not as one span. When the answer is only a date and the month is irrelevant, a text field is faster and smaller. Let the dot mean one thing and say what it is, because it is the only mark on a day besides the selection. --- --- title: Progress description: Progress shows a wait: a spinner when the end is unknown, a bar or ring when it is known. Appetite UI Figma component with a typing indicator and tokens. group: Components source: https://www.appetiteui.com/docs/progress dateModified: 2026-10-03 --- # Progress Updated: October 3, 2026. Progress shows that work is happening: a spinner when the wait has no end in sight, a bar or a ring when it does, and three dots when a reply is being written. ## Preview Two ways to say the app is busy. Spinner when you cannot tell how long, bar when you can. On iOS both are ProgressView, on Android CircularProgressIndicator and LinearProgressIndicator. Specimen: Spinner base 24, Progress Bar at 50. both on brand/base over bg/soft-100. The spinner has 8 frames at 80 ms, so a full turn takes 640 ms. In code that is one rotating arc, and Reduce Motion stops it. Progress Ring shows a known total as a circle and Typing Indicator shows three dots for a reply that is being written. Both have their own section below. Source: the Progress page of the Appetite UI Figma file, read on October 2, 2026. Four sets sit on it, one per section. ## Which sizes does Spinner come in? Spinner has four sizes crossed with eight frames, 32 variants. The arc is identical in all of them and only the box changes. Specimen: sm 16, md 20, base 24, lg 32. ring is 28 percent of the radius: 2.24, 2.8, 3.36, 4.48. Specimen: Frame 1 to 8, held still. 45 degrees apart, eight of them close the circle. Every frame is a track and a 270 degree indicator, both at an inner radius of 0.72, so the ring is 28 percent of the radius and scales with the box. The frames exist so the animation can live in Figma. In code, rotate one arc and never expose Frame. ## How big is a Progress Bar? Progress Bar is 320 by 8, clipping, with an indicator inside it. Five variants set the width and nothing else changes. Specimen: Value 0, 25, 50, 75, 100. indicator widths 0.01, 80, 160, 240, 320. At Value 0 the indicator is a real node 0.01 wide, so it rounds to nothing but is still there. Value is a five stop axis, so real progress means overriding the width on the instance. Bind it to the real number and never animate it for decoration. ## What is Progress Ring for? The bar as a circle, for one figure that deserves room. A 48 box, five values and an optional percent label. Specimen: Value 0, 25, 50, 75, 100. 48 x 48, track and indicator 40 at stroke 4. Progress Ring is a 48 box with a 40 circle drawn at stroke 4: the track in bg/soft-100 and the indicator in brand/base with round caps, starting at 12 o'clock. The Show label boolean prints the percent in the middle in xs/emphasized and is on by default. At Value 0 the indicator is hidden. The ring resizes freely, so draw it at the size the screen needs and keep the label only where it still fits. Specimen: Show label off, at 24 and 32. boxes 24 and 32, the stroke stays 4. ## What is Typing Indicator for? Three dots that say a reply is being written. It loops with no value, for chat and assistant replies. Specimen: Typing Indicator, running, then Frame 1 to 4 held still. 40 x 14, dots 8 on a pitch of 16, one cycle 1200 ms. The set is 40 by 14: three dots of 8 on a pitch of 16, in fg/soft-500. The active dot stands at the top at full opacity and the other two rest 3 lower at 35 percent. Frame 1 raises dot 1, Frame 2 dot 2, Frame 3 dot 3 and Frame 4 none. Each frame is 100 ms of dwell and 200 ms of travel on linear easing, so one cycle takes 1.2 seconds. Pair it with AI / Message set to Streaming, described on the [AI component](https://www.appetiteui.com/docs/ai-component) page. With Reduce Motion on, the first stage specimen rests on Frame 1. ## Properties Four separate sets. Spinner and Typing Indicator animate through a Frame axis, Progress Bar and Progress Ring through Value. | Property | Type | Default | | --- | --- | --- | | `Size` | sm \| md \| base \| lg, on Spinner | sm | | `Frame` | 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8, on Spinner | 1 | | `Value` | 0 \| 25 \| 50 \| 75 \| 100, on Progress Bar | 0 | | `Value` | 0 \| 25 \| 50 \| 75 \| 100, on Progress Ring | 0 | | `Show label` | Boolean, on Progress Ring | true | | `Frame` | 1 \| 2 \| 3 \| 4, on Typing Indicator | 1 | | Set | Variants | Size | | --- | --- | --- | | `Spinner` | 32, Size crossed with Frame | 16, 20, 24, 32 square | | `Progress Bar` | 5, on Value | 320 x 8 | | `Progress Ring` | 5, on Value | 48 x 48 | | `Typing Indicator` | 4, on Frame | 40 x 14 | Frame is a timeline. Expose Size and Value in code and keep Frame inside the animation. No set carries a buffer track or an indeterminate bar. ## Tokens Four colors across the four sets. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/soft-100` | #E9E9EA | #48484A | Spinner track, bar track, ring track | | `brand/base` | #155DFC | #2B7FFF | Spinner arc, bar indicator, ring indicator | | `text/strong-950` | #0E0E0F | #FFFFFF | Ring label | | `fg/soft-500` | #8E8E93 | #AEAEB2 | Typing Indicator dots | In light the track resolves to `colors/gray/100`, in dark to `colors/gray/700`. Brand goes one step lighter in dark. No set has a success, warning or error color. ## How does Progress differ on iOS and Material 3? Both platforms ship a spinner and a bar and animate them natively. Appetite UI draws the same two, adds a ring and a typing indicator, and the file has no Material 3 progress page to compare. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Spinner | `iOS / Spinner` in the Apple pages, Small 14, Regular 20 and Large 35. In code SwiftUI `ProgressView()` or UIKit `UIActivityIndicatorView` | `CircularProgressIndicator`, indeterminate | Appetite UI holds eight frames at 80 ms on a 270 degree arc. The platforms animate it natively, so in code rotate one arc. | | Progress Bar | `iOS / Progress Bar` in the Apple pages, 370 x 4 at Value 0 to 100 percent. In code `ProgressView(value:total:)` | `LinearProgressIndicator` | Appetite UI is 320 by 8 at radius full with five Values to design against. Bind the real number in code. | | Progress Ring | No built in ring. A `Gauge` or a custom progress style draws one. | `CircularProgressIndicator` with a progress value | Appetite UI draws a 48 box with a stroke of 4, round caps and an optional percent label. | | Typing Indicator | None. Messages draws its own typing bubble. | None | A loop of three dots, 1.2 seconds a cycle, for chat and assistant replies. | None of the four is a control, so none has a touch target. Anything a person can tap next to them, such as a cancel button, keeps the minimum of 44 pt on iOS and 48 dp on Android, set by `platform/min-touch-target` in the Platform collection. ## When should I use a spinner and when a bar? Ask one question: do you know the total? If you do, use the bar or the ring bound to the real number. If you do not, use the spinner. - Do: Let the spinner promise nothing but that something is happening. Sign in, a network call, a sync with no total: that is exactly the wait it was drawn for. - Avoid: Never put a percentage next to the spinner. If you can count it, the bar shows it properly. If you cannot, the number is a guess and people will hold you to it. For a flow with a known number of steps, use [Progress Steps](https://www.appetiteui.com/docs/progress-steps). Uploads, downloads and multi step forms know the total, so they get the bar or the ring. Everything else gets the spinner. Use the smallest size the surface allows, keep one on screen at a time, and past a few seconds say what is taking so long. Motion alone says nothing to a screen reader. In code give a bar or ring a progressbar role with its value and a name, and announce that a spinner means loading. With Reduce Motion on, swap the spin for a static arc or a line of text, and let the typing dots rest on Frame 1. --- --- title: Progress Steps description: Progress Steps shows how far someone is through a flow of three to five steps. Appetite UI Figma component: done, current and upcoming markers and tokens. group: Components source: https://www.appetiteui.com/docs/progress-steps dateModified: 2026-10-03 --- # Progress Steps Updated: October 3, 2026. Progress Steps shows how many steps a flow has, and how far through it someone is. ## Preview Where you are in a sequence with a known end. Checkout, onboarding, a form in parts. Done steps carry a check, the current one is outlined with its number, the rest wait. Specimen: Steps 5, Current 3. 272 x 24, markers 24, connector 2. A done step is brand blue with a white check, and the current step is a white circle with a 2 brand outline and a brand number. Upcoming steps sit on bg/soft-100 with their number in text/disabled-400. Source: Progress Steps on the Progress Steps page of the Appetite UI Figma file, read on October 2, 2026. ## How many steps can Progress Steps show? Three, four or five steps. Five is the cap and the file has no sixth. Specimen: Steps 3, 4 and 5, all at Current 2. the connector takes the difference: 84, 42.667, 22. The row is 272 wide at every count, so only the connector moves: 84 at three steps, 42.667 at four, 22 at five. A sixth step would shrink each connector to 9.6 and the row would read as a dotted line. For more than five, use a [Progress Bar](https://www.appetiteui.com/docs/progress#bar) with a step counter in text. ## Progression The same five steps at each position. The check replaces the number the moment a step is behind you. Specimen: Current 1 to 5 at Steps 5. done brand with a check, current outlined, upcoming soft. The connector into the current marker is already brand blue, so the line marks the step you are on as well as the ones behind you. There is no all-done state: at Current 5 the fifth marker is still the outlined current one, so a finished checkout needs a confirmation on screen to say so. ## Properties Two axes, no text, no icons, no slots. | Property | Type | Default | | --- | --- | --- | | `Steps` | 3 \| 4 \| 5 | 3 | | `Current` | 1 \| 2 \| 3 \| 4 \| 5 | 1 | | Set | Variants | Size | | --- | --- | --- | | `Progress Steps` | 12, Steps crossed with Current | 272 x 24, in all twelve | The grid is triangular: Current cannot be higher than Steps, so three of the fifteen combinations do not exist. The numbers inside the markers are plain text with no property on them, so a flow that does not start at 1 is an override on the instance. ## Tokens Five values. Brand does three jobs, and no state color is read. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `brand/base` | #155DFC | #2B7FFF | Done marker, current outline and number, connectors left of the current marker | | `icon/on-color` | #FFFFFF | #FFFFFF | Check on the done marker | | `bg/white-0` | #FFFFFF | #0E0E0F | Current marker fill | | `bg/soft-100` | #E9E9EA | #48484A | Upcoming markers, connectors ahead | | `text/disabled-400` | #AEAEB2 | #8E8E93 | Upcoming numbers | The marker radius is `dimensions/radius/full`. ## How does Progress Steps differ from the iOS Stepper and Material 3? A Stepper changes a number and Progress Steps shows how far through a flow someone is. Neither iOS nor the Material 3 pages of the file draw a step indicator. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Progress Steps | None for a flow. `iOS / Stepper` in the Apple pages (SwiftUI `Stepper`, UIKit `UIStepper`) increments a value, and iOS / Page Control marks a page in a carousel. | None. The file draws no Material 3 stepper or progress indicator. | Appetite UI draws three to five numbered circles joined by a 2 rule, 272 wide, with a check on finished steps. The component that matches the iOS Stepper is Counter Input on the [Input](https://www.appetiteui.com/docs/input) page. | The markers are display only. If a step can be tapped, wrap it in a control with a hit area of at least 44 pt on iOS or 48 dp on Android, the value of `platform/min-touch-target` in the Platform collection, because the marker itself is only 24. ## Guidelines - Do: Five is the ceiling. At five the connector is still 22 wide and the row reads as a path from one circle to the next. - Avoid: Do not add a sixth. The row stays 272, so every connector drops to 9.6 and the path turns into dashes between dots. Use it when the number of steps is known before the user starts and will not change inside the flow: checkout, onboarding, a form split into parts. Decide the count before you show the first step. The circles are a picture of the position. Say it in text as well, for example a heading "Step 3 of 5", and mark the current step in code so VoiceOver and TalkBack read the position. Upcoming numbers use the disabled text color, which has no contrast minimum, so the text must carry what comes next. --- --- title: Radio description: Radio lets people choose exactly one option from a visible set. Appetite UI Figma component: four states with a focus ring, tokens and Material 3 notes. group: Components source: https://www.appetiteui.com/docs/radio dateModified: 2026-10-03 --- # Radio Updated: October 3, 2026. Radio is a form control for choosing exactly one option from a set. ## Preview One choice out of a visible set. Every option stays on screen and exactly one is filled. Click one, or tab to the group and use the arrow keys. Specimen: A live group at Align Left, one selected. row 340, radio 44, content 280 at gap 16. The whole row is the target: the control is a 44 frame around a 22 disc, so the row clears the minimum even though the visible circle is smaller. Content takes the remaining 280 and wraps inside the row. A radio never ships alone, because a single one cannot be turned off again, which is why the preview is a group. Source: Radio, node 211:4275 of the Appetite UI Figma file, read on October 2, 2026. ## Which states does Radio have? Four: Default, Pressed, Focused and Disabled, crossed with one boolean for selected. The file has no Hover state, so a pointer hover moves these specimens toward Pressed. Specimen: Default, Pressed, Focused and Disabled, each unselected then selected. 44 target, 22 disc, center 18 or 10. The disc is 22 and the center circle 18, optically matched to the 24 square of Checkbox so the two sit side by side in a 44 target. The selected dot is 10 and static white in both modes. Focused is the focusRing/brand effect style, a 2 pt gap in the surface color and then a 2 pt ring in brand/base, drawn on the disc. The unselected disc is bg/sub-200, so an empty radio stays visible on a white screen. The ring is the 22 disc showing round an 18 circle in bg/white-0. Pressed while unselected turns the disc brand blue. Disabled while unselected has no center circle, a flat gray disc. 8 variants, State crossed with Active. They are there to be read, so nothing in this frame takes a click. ## Label row The radio with a title, an optional description, and a side to sit on. The whole row is the tap target. A group of them is how the control ships. Specimen: Align Left and Align Right. 340 row, 44 radio, 280 of content, gap 16. Specimen: Show Description off, the same two aligns. title 18/28 Semi Bold, description 14/20 Regular. Align moves the radio from one end to the other and changes nothing else. Turning the description off drops the 14/20 line, and the 44 target sets the floor for the row height. The title is 18/28 Semi Bold, so a long option name uses the width fast. Both rows in each frame stay selected on purpose, because they are one variant shown twice. ## Properties Two axes on the control, four properties on the label row. | Property | Type | Default | | --- | --- | --- | | `State` | Default \| Pressed \| Disabled \| Focused, on Radio | Default | | `Active` | True \| False, on Radio | False | | `Align` | Left \| Right, on _Radio Label | Left | | `Label` | Text, on _Radio Label | Title of radio | | `Description` | Text, on _Radio Label | Insert the label description here. | | `Show Description` | Boolean, on _Radio Label | True | | Set | Variants | Size | | --- | --- | --- | | `Radio` | 8, State crossed with Active | 44 x 44 | | `_Radio Label` | 2, on Align | 340 wide, 48 tall with a description | There is no group component. A radio group is however many label rows you place, and keeping exactly one Active is your job. Nothing carries a name or a value, so the wiring lives in code. ## Tokens Every value the radio reads, resolved through its aliases to the primitive underneath. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/sub-200` | #D1D1D6 | #636366 | Unselected disc | | `brand/base` | #155DFC | #2B7FFF | Selected disc, pressed unselected disc, focus ring | | `brand/pressed` | #193CB8 | #155DFC | Disc when selected and pressed | | `bg/white-0` | #FFFFFF | #0E0E0F | Center circle when unselected, and the gap in the focus ring | | `icon/on-color` | #FFFFFF | #FFFFFF | Dot when selected | | `bg/soft-100` | #E9E9EA | #48484A | Both disabled discs | | `fg/disabled-400` | #AEAEB2 | #8E8E93 | Disabled dot | | `text/strong-950` | #0E0E0F | #FFFFFF | Title | | `text/sub-700` | #48484A | #C7C7CC | Description | Selected and pressed, the disc fills with brand/pressed, a step darker than brand/base in Light and in Dark. The center circle is bg/white-0 and opaque, so an unselected radio on any other surface shows a disc of the wrong tone. ## How does Radio differ on iOS and Material 3? iOS has no radio button, and Material 3 has one with a 48 by 48 target. Appetite UI Radio is one component with a 44 pt target for both. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Radio | None. iOS shows one choice among several as an inline picker or a list row with a checkmark. | M3 / Radio, 48 by 48, Selected by Is Enabled | Appetite UI draws a 22 disc in a 44 target and adds Pressed and Focused. The Material 3 set has no Pressed, Hovered or Focused variant. | The minimum touch target is 44 pt on iOS and 48 dp on Material 3, set by `platform/min-touch-target` in the Platform collection. The 44 frame meets the iOS minimum. On Android, add 4 dp of hit area in code. ## Guidelines - Do: Exactly one filled, and every option on screen. If the user cannot see all the choices at once, the control is a Dropdown or a Picker, not this. - Avoid: Two filled is a Checkbox wearing the wrong shape. Round means one, square means any number, and people read that before they read the label. Use it for two to five options that fit on screen together and deserve to be compared. One option is not a choice, and past five a list or a picker wins. Always start with one selected, and never use a radio for an action. --- --- title: Rating description: Rating shows a score out of five stars and collects one from a tap. The Appetite UI Rating for Figma: Display, Interactive and Score, tokens and iOS notes. group: Components source: https://www.appetiteui.com/docs/rating dateModified: 2026-10-03 --- # Rating Updated: October 3, 2026. Rating shows a score out of five, and collects one when someone is asked to give it. ## Preview Stars in two jobs. Display reports a score you cannot change, Interactive collects one. Neither iOS nor Android ships a rating control, so both are yours to build. Specimen: Display at 4.2, then Interactive at 3. 16 stars at gap 2, 36 stars at gap 8. Source: the Rating and Rating / Score sets of the Appetite UI Figma file, read on October 2, 2026. Display sits inline beside a name or a place. Interactive stands alone and expects room around it. The score reads 4.2 while four stars are filled, because stars cannot draw a decimal. ## Display Read only and inline, in three variants: Rating 5, 4 and 3. Stars, a score and a count. Specimen: Rating 5, 4 and 3. rows measure 156, 152 and 144. The star row is a fixed 88 wide whatever the score, so only the text after it changes the width of the row. Empty stars are gray silhouettes. Display ships Rating 5, 4 and 3, and the count is part of every variant. For a score of 2 or 1, override the star fills on an instance of Rating 3. ## How does the Interactive Rating work? It is the input version: 212 wide and 84 tall, with five 36 stars and a hint that names the score in words. Press the stars. Specimen: Selected 0, 3 and 5. 212 x 84, stars 212 x 36 at gap 8. Empty stars switch technique here: the same path stroked at 2.5 rather than filled, so they read as outlines. That keeps the 36 stars from looking heavy. The hint names the step in words: the file draws Tap to rate, Fair and Excellent. The live stars also say Terrible, Poor and Good for the steps in between. Interactive ships Selected 0, 3 and 5. Build the other steps by filling more stars on an instance. ## When should I use Rating / Score? Use it for cards and list rows where five stars would be too heavy: one star and a number. The full component stays on Rating. Specimen: Rating / Score, Size sm and md. sm 39 x 20 with a 13 star, md 42 x 20 with a 16 star. Rating / Score is a separate set with one axis, Size, and one text property, Score, which defaults to 4.9. Size sm draws a 13 star and md a 16 star beside a 14 pt number, 4 apart. It has no count and no stars to fill, so it is a read only summary. ## Properties Rating has three variant axes and six variants. Rating / Score has one axis and a text property. | Property | Type | Default | | --- | --- | --- | | `Style` | Display \| Interactive | Display | | `Rating` | 5 \| 4 \| 3 \| 0 | 3 | | `Selected` | 0 \| 3 \| 5 \| None | None | | `Size` | sm \| md, on Rating / Score | sm | | `Score` | Text, on Rating / Score | 4.9 | | Combination | Reads | Size | | --- | --- | --- | | Display, Rating 5, 4 and 3 | Selected is always None | 156, 152 and 144 x 28 | | Interactive, Selected 0, 3 and 5 | Rating is always 0 | 212 x 84 | | Rating / Score, Size sm and md | Score text | 39 and 42 x 20 | Rating holds the value for Display and Selected holds it for Interactive, and each is dead in the other style. Widths move with the text, and the star row is 88 in every Display variant. Score, count and hint are text overrides, so a real number means editing the instance. There is no half star, so 4.6 shows four stars and the number carries the rest. ## Tokens Four colors, and the gold is the odd one out. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `colors/yellow/400` | #FFB900 | #FFB900 | Filled stars, one value in both modes | | `bg/soft-100` | #E9E9EA | #48484A | Empty stars, as a fill in Display and a 2.5 stroke in Interactive | | `text/strong-950` | #0E0E0F | #FFFFFF | The score | | `text/sub-700` | #48484A | #C7C7CC | The count and the hint | The gold is a primitive with a single mode, so it stays #FFB900 while everything around it themes. There is no semantic token for it, so a second gold needs a primitive of its own. Source: the Foundations and Color Tokens collections of the Appetite UI Figma file, read on October 2, 2026. ## How does Rating differ on iOS and Material 3? Rating has no iOS or Material 3 counterpart, because neither platform ships a star rating control. Build it from this component, and treat the stars as buttons. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Rating, Rating / Score | No rating control. The Apple pages draw stars only inside iOS / Review Prompt, the system review alert, and SwiftUI has no rating view | None in the Material 3 pages. Compose has no rating composable | Both platforms leave the control to the app, so the stars, their targets and their announcements come from this set. | The minimum touch target is 44 pt on iOS and 48 dp on Android, set by `platform/min-touch-target` in the Platform collection. The Interactive stars are 36 at gap 8, so they repeat every 44: on iOS the targets tile exactly once each star's hit area runs to the middle of its gap, and on Android widen the row to a 48 pitch. See [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge), [iOS](https://www.appetiteui.com/docs/ios) and [Material 3](https://www.appetiteui.com/docs/material-3). ## Guidelines - Do: Put the number next to the stars. Four stars could be anything from 3.5 to 4.4, and the count is what tells the reader whether to believe it. - Avoid: Stars alone are a decoration. Without a count, a perfect score from two people outranks a good one from two thousand, and nobody can tell. Use Display where a score is one attribute among several, and Score where even that is too much. Use Interactive only where rating is the point of the screen. Do not fake a half star by scaling the glyph, because the set has no half state. Give the stars a text alternative. A Display row should read as one sentence, such as Rated 4.2 out of 5 from 128 reviews, with the glyphs hidden from assistive technology. An Interactive row is a group of five radio buttons with a name for the group and arrow key movement between them, which the live stars do. --- --- title: Search description: Search finds content as you type. The Figma component has a 44 tall Field, a 60 tall Hero, three states, optional voice input and light and dark tokens. group: Components source: https://www.appetiteui.com/docs/search-field dateModified: 2026-10-03 --- # Search Updated: October 3, 2026. Search lets people find content by typing a query, with voice input when the keyboard is in the way. ## Preview A search bar for the top of a screen or the first row of a list, with the microphone as an optional second way in. Type in it: the bar fills and turns white as soon as there is text. Specimen: State follows what you type. 44 tall, full radius, padding 8 and 16, width fills the parent. Empty is State Default and anything typed is State Searched. The fill, the 1 pt edge and the ink change together, the mic gives its place to an x, and the x clears the field. While the field has the keyboard it takes State Active, a 1.5 pt brand edge. The component fills its parent, so the 332 here comes from the variant frame. ## Which states does Search have? Three states. Empty is a filled capsule with no edge, the typing state has a brand edge and a caret, and a query that has been entered is a white bar with a gray edge. Specimen: State Default, Searched, Active, all at Style Field. bg/weak-50 no border, bg/white-0 with 1px, bg/white-0 with 1.5px brand. Field is 44 tall at full radius. Active is a 1.5 pt brand edge on a white bar with a 2 by 22 caret. Default to Searched: the fill goes from weak gray to white, a 1 pt border appears, and the icon and the text step from the soft token to the strong one. The trailing icon changes job too: the microphone offers another way to start and the x clears what is there. Active is the same white bar with the brand edge and the caret after the query. ## When should I use Hero instead of Field? Use Field inline in a form or a header, and Hero floating over a photographic header on a home screen, where it ends in a real button. Specimen: Style Hero, all three states. 345 x 60, full radius, padding 18 and 8, gap 10, dropShadow/lg. Hero is 16 taller, 13 wider and carries a shadow, so it reads as an object sitting on the page. The leading search icon is 20 instead of 24, and the trailing slot is a 44 pt icon-only Button on bg/strong-950 holding a sliders icon. Hero has no Show Mic, because it has no mic. Its Searched state changes only the text color, where Field's Searched also changes the fill, the edge and the trailing icon. ## How do I hide the microphone? One boolean, Show Mic, decides whether Field in State Default ends on a microphone. Specimen: Show Mic true and false, both at State Default, Style Field. the query row is the only thing that stretches. Show Mic hides the microphone in State Default and nothing else. State Searched always shows the x, and Hero never shows a mic. A 20 wide empty slot sits before the trailing icon in the file, so with the mic off the text ends 20 short of the padding. ## How does Search differ on iOS and Material 3? The Apple Platform and Material 3 pages of the file have no search field, so there is no mirror to compare. Appetite UI draws a capsule 44 tall, which equals the iOS minimum touch target. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | `Search`, Field | None in the file beyond the Search Role tab of iOS / Tab Bar. SwiftUI offers the searchable modifier. | None in the file. Compose offers SearchBar. | Field is 332 x 44 at full radius with a mic and a clear button. | | `Search`, Hero | None in the file | None in the file | Hero is 345 x 60 with a shadow and a 44 pt action button. | The minimum touch target comes from `platform/min-touch-target`: 44 pt on iOS and 48 dp on Android. Field is exactly 44 tall, so on Android raise the hit area to 48 in code. Hero clears both. See [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge) for how one screen switches between the platforms. ## Properties Two variant properties, one boolean and one text, with the six variants they make. | Property | Type | Options | Default | | --- | --- | --- | --- | | `State` | Variant | Default, Searched, Active | Default | | `Style` | Variant | Field, Hero | Field | | `Placeholder` | Text | any string | Search | | `Show Mic` | Boolean, Field only | on, off | on | | Part | What it is | Size | | --- | --- | --- | | `Query row` | Field only. Icon and text, the only child that stretches | fills, 28 tall | | `Icon slot` | Field only. An empty rectangle with no fill and no stroke | 20 x 20 | | `Typed` | Active only. The query and a caret, 2 apart | hugs, caret 2 x 22 | | `Spacer` | Hero at State Active only. An empty flexible frame | fills, 1 tall | | `Action` | Hero only. An icon-only Button on bg/strong-950 | 44 x 44, icon 22 | | `mic` or `x` | Field only. Swapped by variant | 24 x 24 | Placeholder is a text property, and the same text node carries the query at one style, 18/28 Semi Bold. There is no loading or disabled state. Clearing the field and handling the action button are code you write. Six variants. Source: the Search page of the Appetite UI Figma file, read on October 2, 2026. ## Tokens Every value the component reads, and several pairs that are the same value under two names. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/weak-50` | #F4F5F5 | #242427 | The Field bar in Default | | `bg/white-0` | #FFFFFF | #0E0E0F | Field in Searched and Active, and every Hero | | `border/soft-100` | #E9E9EA | #2F2F31 | The 1 pt inside edge, Field Searched and Hero | | `brand/base` | #155DFC | #2B7FFF | The 1.5 pt Active edge and the caret | | `bg/strong-950` | #0E0E0F | #FFFFFF | The Hero action button | | `fg/white-0` | #FFFFFF | #0E0E0F | The sliders icon on that button | | `text/soft-500` | #8E8E93 | #AEAEB2 | Placeholder and search icon, with fg/soft-500 on the mic | | `text/strong-950` | #0E0E0F | #FFFFFF | Query text and icons once there is a query | The icons read `fg/soft-500` and `fg/strong-950`, and the text beside them reads `text/soft-500` and `text/strong-950`. Each pair resolves to the same primitive in both modes. `bg/strong-950` and `fg/white-0` are an inverting pair, so the Hero button is a black circle with a white icon in Light and a white circle with a black icon in Dark. The Hero shadow is the effect style `dropShadow/lg`: 0 12 18 at spread minus 3 on black at 8 percent, and 0 5 6 at spread minus 5 on black at 5 percent. The product soft text color, #8E8E93, measures 3.26:1 on white, under the 4.5:1 that small text needs. It is a documented product choice for the placeholder and the search icon, so raise it in your own product if the placeholder carries essential information. In code the field takes focus from a tap or from the keyboard and shows the 1.5 pt brand edge of State Active. Field is 44 pt tall, which meets the iOS target, and on Android it needs a 48 dp hit area. ## Where does Search belong on a screen? Field goes in the Top Bar or at the head of a list, not floating in the middle of content. - Do: Keep the placeholder to a word or two. The search icon and its gap take 32 before the text starts, and the slot and mic take another 44 after it. - Avoid: Do not write a sentence in the field. At 18/28 Semi Bold it truncates in the middle of the promise. Hero is the one exception: a home screen header, over an image, with the action button doing something real. Turn Show Mic off unless voice input works, because an icon that opens nothing costs a touch target. --- --- title: Segmented Control description: Segmented Control switches between two to five views of one content or setting. Appetite UI Figma component: two sizes, tokens and iOS notes. group: Components source: https://www.appetiteui.com/docs/segmented-control dateModified: 2026-10-03 --- # Segmented Control Updated: October 3, 2026. Segmented Control switches between two to five views of the same content. ## Preview A mutually exclusive switch between views of the same content, applied the moment it is picked. Default size, three segments. The specimen is live, so pick one. Specimen: Segmented Control, Size Default, Tabs 3. track 340 x 48, padding 4, segment 110.67 x 40, radius full. The component exposes two properties, Size and Tabs. Every label reads Option because the label lives on a nested selector instance, and so do Active, Icon and Icon Swap, so a real control means reaching into each segment one at a time. Every variant sets Icon off. Switching moves the pill with motion/duration/base, 200 ms on the standard curve. ## How many segments can a Segmented Control hold? Two to five segments in the same 340 track. The 4px padding never moves, so segments split the remaining 332 evenly; only their width changes. Five is the cap, the same as Tabs. Specimen: Tabs 2, 3, 4, 5. 332 split evenly, at Size Default with Icon off. The track is pinned to 340 and each segment fills an equal share of the 332 left over: 166, 110.67, 83 and 66.4 wide. A segment spends 12 of padding on each side, and 6 once there are five, so five leave 54.4 for the label. ## How tall is a Segmented Control? Two heights, 48 and 38. The segment carries the change: 40 tall at padding 8 and 12 becomes 30 at 6 and 12, label 16/24 to 14/20 at letter spacing .1. Track padding, gap and radius hold. Specimen: Size Default, Size Small. track 48 / 38, segment 40 / 30, label 16 / 14. The track gets 48 and 38 once a 40 or a 30 segment sits inside 4 of padding. The icon, when you switch it on, is 16 square in both sizes, so at Small it takes a bigger share of a shorter segment. ## Which states does Segmented Control have? One state, held by exactly one segment. Active takes the bg/white-0 fill, dropShadow/xs and text/strong-950. Inactive carries no fill and drops to text/sub-700. There is no Pressed or Disabled variant in the file. Specimen: Active True, Active False. fill bg/white-0 with dropShadow/xs, then no fill. Set Active on exactly one segment. It lives on the nested selector, so a three segment variant carries three independent booleans and nothing stops all three being on at once. Keep that rule in your code. ## Properties Two variant axes on the published component. The rest sit on the selector inside it, a building block not meant for direct use. | Property | Type | Default | | --- | --- | --- | | `Size` | Default \| Small | Default | | `Tabs` | 2 \| 3 \| 4 \| 5 | 2 | | `Active` | True \| False, on the selector | False | | `Icon` | Boolean, on the selector, set false in every variant | true | | `Icon Swap` | Instance swap, on the selector | circle | Segmented Control ships 8 variants, two sizes across four tab counts. The selector ships four, Active across Size. ## Tokens Every value the component reads, resolved through its aliases to the primitive underneath. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/weak-50` | #F4F5F5 | #242427 | The track | | `bg/white-0` | #FFFFFF | #0E0E0F | The active segment | | `text/strong-950` | #0E0E0F | #FFFFFF | The active label | | `text/sub-700` | #48484A | #C7C7CC | Every other label | | `fg/soft-500` | #8E8E93 | #AEAEB2 | The icon, in both states | Radius is `dimensions/radius/full` on both track and segment. The active fill carries `dropShadow/xs`: 0 1px 2px at 4 percent over 0 4px 4px at 1 percent. Accordion and Card reach for the same pair. In dark, bg/weak-50 lands on #242427 while the active segment lands on #0E0E0F, so the selected pill is darker than the groove holding it. ## How does Segmented Control differ on iOS and Material 3? iOS has its own Segmented Control, wider and in two other heights. The Material 3 page of the file has no segmented control. Appetite UI Segmented Control is one component with a 340 wide track. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Segmented Control | iOS / Segmented Control, 370 wide, Size Small at 32 high and Large at 50 high by Segments 2 to 5 | None in the file. Material 3 has a segmented button of its own, which the file does not include. | Appetite UI is 340 wide at 48 and 38 high with a radius of full on both track and pill. The counts match: two to five segments. | The minimum touch target is 44 pt on iOS and 48 dp on Material 3, set by `platform/min-touch-target` in the Platform collection. Default clears 44 pt. Small is 38 high, so give it 44 pt of hit area in code. ## When should I use Segmented Control instead of Tabs? Use Segmented Control when the switch belongs to a setting and Tabs when it belongs to the content below it. - Do: Keep the set short and the labels to one word. Segments take an equal share, so the longest label decides the room every other segment gets. - Avoid: Do not push five long labels through a Default track. Each segment gets 66.4 and spends 12 on padding, so a word wider than 54 clips. Go Small, drop the icon, or use Tabs. Both cap at five segments. Segmented Control is a pill in a groove and applies on pick, and Tabs is an underline with no track. They do the same job in opposite chrome, so pick one per screen. --- --- title: Skeleton description: Skeleton holds the shape of content while it loads, as a line, a circle or a block with a slow pulse. Appetite UI component for Figma, iOS and Android. group: Components source: https://www.appetiteui.com/docs/skeleton dateModified: 2026-10-03 --- # Skeleton Updated: October 3, 2026. Skeleton holds the shape of content while it loads, so the screen does not jump when it arrives. For lists and cards it beats a spinner. ## Preview A placeholder that holds the shape of what is coming, so the screen does not jump when the data lands. Stack three to five rows while the data loads. Specimen: _Skeleton List Row, repeated three times. 360 x 72, circle 40, lines at gap 8, pulse 480ms. One row is a 40 circle, a line that fills the rest and a short line under it, all breathing together. The pulse runs 480ms on a linear curve, the timing named `motion/skeleton/pulse`. ## Which shapes does Skeleton have? Three: Line, Circle and Block, and nothing else. No text, no icons, no content of any kind. Specimen: Line, Circle and Block. 200 x 12, 40 x 40, 200 x 120. Line and Circle are both radius full, so a 12 tall line is a stadium and a 40 square is a disc. Block is the only one on a real radius token, `dimensions/radius/lg` 12, so it reads as a card. Every size here is a default meant to be resized on the instance. ## How does Skeleton pulse? Two variants make one breath: Pulse 1 is the stronger gray and Pulse 2 the weaker. Held still here so you can see both. Specimen: Pulse 1 then Pulse 2, at Line, Circle and Block. bg/sub-200 to bg/soft-100. Pulse is a timeline, not a state. Both ends move the same way in either theme: light runs #D1D1D6 down to #E9E9EA, dark #636366 down to #48484A, so it always breathes from more contrast to less. In code, animate between the two colors and alternate. When the reader prefers reduced motion, show Pulse 1 without the animation. ## How does Skeleton differ on iOS and Material 3? Neither platform draws a skeleton in the Figma file. SwiftUI offers the redacted modifier with the placeholder reason, and Material 3 leaves loading to its progress indicators. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Skeleton, Line 200 x 12, Circle 40, Block 200 x 120 | SwiftUI redacted(reason: .placeholder), no Figma component | No counterpart, progress indicators only | Appetite UI draws the shapes you place. SwiftUI blanks the real content in place. Neither platform defines a pulse | A skeleton has no interaction, so no touch target applies. It carries no text, so announce the loading state once on the container, for example with a label such as Loading, and keep the gray shapes out of the reading order. The shapes sit on `bg/sub-200`, which is too faint to carry contrast, so they signal shape and nothing else. See [Progress](https://www.appetiteui.com/docs/progress) for a spinner. ## Properties Two axes, six variants, and one ready made row beside them. | Property | Type | Default | | --- | --- | --- | | `Type` | Block \| Circle \| Line | Block | | `Pulse` | 1 \| 2 | 1 | | Component | Variants | Size | | --- | --- | --- | | `Skeleton` | 6, Type crossed with Pulse | 200 x 12, 40 x 40, 200 x 120 | | `_Skeleton List Row` | One component, no properties | 360 x 72 at radius 4 | Check the ready made row against the list it stands in for before you use it as is. It is 360 by 72 at radius 4 with a 16 gap, a circle at radius full and 272 of content, and none of that is bound to the List component. A stack of these holds the shape of the list only if you resize the instance to match. ## Tokens Two grays and one piece of motion. That is the whole component. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/sub-200` | #D1D1D6 | #636366 | Pulse 1, the stronger end of the breath | | `bg/soft-100` | #E9E9EA | #48484A | Pulse 2, the weaker end | | Motion token | Resolves to | Value | | --- | --- | --- | | `motion/skeleton/pulse/duration` | motion/duration/slower | 480ms | | `motion/skeleton/pulse/easing` | motion/easing/linear | cubic-bezier(0, 0, 1, 1) | Linear is right here and unusual everywhere else in the system: a breath that eases reads as a thing being tapped. No semantic loading token exists: the two grays are the background tokens used for dividers and empty states, so a skeleton on `bg/soft-100` loses one end of its pulse. ## Guidelines - Do: Repeat the row and let it hold the shape of the list underneath. Three to five is the range to use, and nothing jumps when the data arrives. - Avoid: Do not stand one gray block in for a list. It promises a shape the content will not have, so the layout jumps anyway and it says less than a spinner would. Reach for it when the layout is known and the wait is short: lists, cards, a profile header. Match the skeleton to the real thing and resize the instance rather than accept the defaults. Do not skeleton a whole screen, because a page of gray is harder to read than one spinner. Cap it: past about ten seconds, switch to an error state. --- --- title: Slider description: Slider sets a value or a range by dragging a thumb along a track. The Appetite UI Slider for Figma: Percentage and Range sets, tokens and iOS notes. group: Components source: https://www.appetiteui.com/docs/slider dateModified: 2026-10-03 --- # Slider Updated: October 3, 2026. Slider lets people set a value, or a range, by dragging a thumb along a track. ## Preview Continuous value selection across a known range. A label, an amount, and a 324 wide track with one thumb on it, inside a 340 wide frame. Drag it, or focus it and use the arrow keys. Specimen: Percentage 50, label and amount on. 340 x 40, track 324 x 6, thumb 16. Source: the Slider and Range Slider sets of the Appetite UI Figma file, read on October 2, 2026. The label hugs left at 14/20 and the amount fills the rest of the row at 12/16, on the same baseline. The thumb is a 16 white circle with a 1 stroke in border/sub-200, a brand dot and dropShadow/sm. The stroke and the shadow keep it visible on a light track and a light screen. ## Which values can Slider take? Five variants, each a progress width on the same 324 track. The thumb center sits on the end of the line. Specimen: Percentage 0, 25, 50, 75 and 100. progress 1, 81, 162, 243, 324. Each step is a quarter of 324, so the progress line runs 81, 162, 243 and 324. At 0 percent the line is 1 wide, a real node that rounds to nothing, and the dot inside the thumb turns gray so an empty slider does not look filled. The track is inset 8 on each side, so the thumb stays inside the 340 frame at both ends. ## How does Range Slider work? Range Slider is a second set with a thumb at each end of the line. Eleven of the twenty Left by Right combinations exist. Specimen: Left 0 with Right 0, then 0 to 25, 25 to 50, 50 to 75, 75 to 100. the first one is the default variant. Specimen: Wider spans: 0 to 50, 25 to 75, 50 to 100, 0 to 75, 25 to 100, 0 to 100. the same two thumbs further apart. Left 0 with Right 0 is the default on both axes. It is the empty range: the thumbs sit at the two ends like 0 to 100, but the line and both dots are bg/soft-100, so set both bounds on every instance you use. Every other variant puts both thumbs on the bound it marks and paints the span in brand/base. The range specimens are static, because a range has two bounds and one pointer cannot say which of them moved. ## Properties Two sets, three variant axes, and the same three text and visibility properties on both. | Property | Type | Default | | --- | --- | --- | | `Percentage` | 0% \| 25% \| 50% \| 75% \| 100%, on Slider | 0% | | `Left Range` | 0% \| 25% \| 50% \| 75%, on Range Slider | 0% | | `Right Range` | 0% \| 100% \| 25% \| 50% \| 75%, on Range Slider | 0% | | `Label` | Boolean, on both | True | | `Label Text` | Text, on both | Label | | `Amount Number` | Text, on both | Value | | Set | Variants | Size | | --- | --- | --- | | `Slider` | Five, on Percentage | 340 x 40 | | `Range Slider` | Eleven of twenty, Left crossed with Right | 340 x 40 | Percentage is a five step axis, so any value between the quarters is an override. The set has no states: no pressed, no disabled and no focused variant. The live specimens add a brand halo under a pointer and a 2 pt focus ring from the keyboard. With Label off the component is 16 tall. ## Tokens Six colors and one effect style, resolved in Light and Dark. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `brand/base` | #155DFC | #2B7FFF | Progress line and the dot inside the thumb | | `bg/soft-100` | #E9E9EA | #48484A | The track, the dot at 0 percent, and the empty Range Slider default | | `static/static-white-0` | #FFFFFF | #FFFFFF | The thumb, one value in both modes | | `border/sub-200` | #D1D1D6 | #48484A | The 1 stroke round the thumb | | `text/strong-950` | #0E0E0F | #FFFFFF | Label | | `text/sub-700` | #48484A | #C7C7CC | Amount | | `dropShadow/sm` | effect | effect | The thumb | The thumb reads static/static-white-0, so it stays white on the dark theme. The stroke separates it from a light track and carries the thumb in dark. ## How does Slider differ on iOS and Material 3? Appetite UI Slider is one shape on both platforms: a 6 tall track with a 16 round thumb, plus a label and an amount. The iOS page of the file has its own slider, and the Material 3 pages have none. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Slider and Range Slider | iOS / Slider, 320 x 28, State Idle and Disabled by Value 0 to 100, with a Show Ticks switch that is off by default | None in the file. Compose ships Slider and RangeSlider | The iOS knob is a 38 x 24 white capsule with no stroke under a soft shadow, on a 6 tall track at radius 3, and the fill ends under the knob center. Show Ticks adds five 4 pt dots along the track. Disabled recolors the fill to iOS/systemGray and keeps the knob white. Appetite UI uses a 16 circle with a stroke and a shadow. iOS has no range set and no label row. | The minimum touch target is 44 pt on iOS and 48 dp on Android, set by `platform/min-touch-target` in the Platform collection. The 16 thumb is far under both, and the file draws no hit area, so give the track at least that height in code. The iOS knob is 24 tall, which also needs padding. See [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge), [iOS](https://www.appetiteui.com/docs/ios) and [Material 3](https://www.appetiteui.com/docs/material-3). ## Guidelines - Do: Keep the amount on screen. A thumb three quarters along says nothing by itself, and the number is the only part of this component that names the value. - Avoid: Do not turn the label off and leave the track on its own. Without a readout the user is guessing, and a slider nobody can read is decoration. Reach for a slider when the direction matters more than the exact number: volume, brightness, a price filter. When the value has to be exact, a stepper or a field beats it. Update the amount live as the thumb moves, because the number is the feedback. Use the range set for genuine bounds, not for two unrelated values that share a scale. Expose the value to assistive technology. A slider is a role with a name, a minimum, a maximum and a current value, the arrow keys move it one step, Page Up and Page Down move it ten, and Home and End jump to the ends. The label in this component is its accessible name. --- --- title: Tab description: Tab switches between related views on one screen. Appetite UI Figma component: two sizes, two to five tabs, hairline and rule, tokens and platform notes. group: Components source: https://www.appetiteui.com/docs/tab dateModified: 2026-10-03 --- # Tab Updated: October 3, 2026. Tab switches between related views inside a single screen. ## Preview An in-page switch between sibling sets of content. It changes what sits below it, never the top-level destination. Default size, three tabs. Live specimen, pick one. Specimen: Tabs, Size Default, Tabs 3. track 340 x 48, padding 0 and 4, tab 110.67, rule 2. Tab does the job of Segmented Control with a different build. The row has no track fill and no radius, only side padding: three tabs and one rule. The parent exposes Size and Tabs; the label, the icon and the active tab live on the nested selectors. Switching moves the rule with motion/duration/base, 200 ms on the standard curve. A 1 pt hairline in border/soft-100 runs under the whole row. ## How many tabs can a row hold? Two to five tabs in the same 340 track. The 4 pt side padding never moves, so tabs split the remaining 332 evenly; only width changes. The 2 pt rule sits under the active tab and the 1 pt hairline under the whole row. Specimen: Tabs 2, 3, 4, 5. 332 / n at Size Default, Icon off. At Default a tab spends 16 of padding per side at two and three tabs, 12 at four and 6 at five, so five tabs leave 54.4 for the label. Widths match Segmented Control, 166, 110.67, 83 and 66.4, because both split the same 332. Long labels behave differently: Segmented Control clips inside a visible pill and a tab has no edge, so keep five labels to one short word each. Tabs ships 8 variants, two sizes across four tab counts. ## How tall is a Tab? Two heights, 48 and 36. The tab fills the track, so only padding and label change: 12 and 16 with a 16/24 label becomes 8 and 12 with 14/20 at letter spacing .1. The rule stays 2 pt and the icon stays 16. Specimen: Size Default, Size Small. track 48 / 36, padding 12 / 8, label 16 / 14. Tab is 48 and 36 high, where Segmented Control is 48 and 38. They line up at Default and sit two apart at Small, because a tab has no 4 pt track padding to absorb. The rule holds at 2 pt and the icon, when you switch it on, holds 16. ## Which states does Tab have? One state, held by one tab. Active draws a 2 pt brand/base rule inside its own bottom edge and turns the label brand/base. Inactive has no rule and a text/sub-700 label. There is no Pressed or Disabled variant in the file. Specimen: Active True, Active False. 2px rule brand/base inside, then nothing. Set Active on exactly one tab. It lives on the nested selector, so every tab carries its own boolean, and it defaults to False. The rule is a stroke on the bottom edge alone, so Figma's inspector shows a mixed stroke weight: read it as an underline. ## Properties Two variant axes on the published component. The rest sit on the selector inside it, a building block not meant for direct use. | Property | Type | Default | | --- | --- | --- | | `Size` | Default \| Small | Default | | `Tabs` | 2 \| 3 \| 4 \| 5 | 2 | | `Active` | True \| False, on the selector | False | | `Icon` | Boolean, on the selector, set false in every variant | true | | `Icon Swap` | Instance swap, on the selector | circle | The selector ships 4 variants, Active across Size, and is composed into every Tabs variant. ## Tokens Every value the component reads, resolved through its aliases to the primitive underneath. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `brand/base` | #155DFC | #2B7FFF | The rule, the active label and the active icon | | `text/sub-700` | #48484A | #C7C7CC | Every other label | | `border/soft-100` | #E9E9EA | #2F2F31 | The 1 pt hairline under the whole row | | `fg/soft-500` | #8E8E93 | #AEAEB2 | Every other icon, when switched on | Radius is `dimensions/radius/none` on the track and on the tab. There is no fill and no shadow, which separates Tab from Segmented Control. Four colors are the whole palette, and brand/base does three jobs: the rule, the label and the icon. ## How does Tab differ on iOS and Material 3? The iOS and Material 3 pages of the file hold bottom bars for top-level destinations and no in-page tab row. Appetite UI Tab is the in-page switch, 340 wide with a rule under the active tab. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Tab | None in the file. iOS / Tab Bar on the Apple Platform pages is the bottom bar for top-level destinations. | None in the file. M3 / Navigation bar is the bottom bar for top-level destinations. | Appetite UI Tab is 48 or 36 high with a 2 pt rule and a 1 pt hairline and never changes the top-level destination. For that, use Navigation. | The minimum touch target is 44 pt on iOS and 48 dp on Material 3, set by `platform/min-touch-target` in the Platform collection. Default is 48 high and clears both. Small is 36 high, so give it a 44 pt hit area on iOS and 48 dp on Android in code. ## When should I use Tab? Use Tab for sibling content on one screen and Navigation for top-level destinations. - Do: Use tabs for sibling content on one screen. The tab swaps what sits under it and leaves the rest of the screen where it was. - Avoid: Do not move between top-level destinations with tabs. That is Navigation, and a tab that replaces the whole screen leaves no way back. Tab and Segmented Control both switch between two and five things and are 48 high at Default, yet they do different jobs. A segmented control is a setting that applies on pick, and tabs belong to the content below them. Pick one per screen. --- --- title: Table description: Table is a mobile data table for Figma: a pinned lead column, sideways scroll, sortable headers and three row heights for iOS and Android apps. group: Components source: https://www.appetiteui.com/docs/table dateModified: 2026-10-03 --- # Table Updated: October 3, 2026. Table shows rows of data on a phone. It pins the leading column, scrolls the others sideways and keeps every row in one table at one height, in three densities, so people can compare values across rows. ## Preview Click a header to sort, scroll the table sideways to slide the values under the pinned column, and switch the row density. Specimen: Table, Layout Inset, Density Default, Show pinned column, Show actions column. Inset 361 x 268, header 44, rows 56, lead column 160. Rows are separated by a hairline: the table draws no row hover and no striping. The Table page of the file holds Table, Trend Chip and Key Value Row. A cell can also hold the Sparkline from the [Chart](https://www.appetiteui.com/docs/chart) page. Read from the Table set, node 16152:1156, on October 2, 2026. ## Which layouts does Table have? Table has two layouts. Inset keeps the table inside a card or a padded screen, and Full bleed runs it from one screen edge to the other. Specimen: Layout Inset, Layout Full bleed. Inset 361 x 268, radius 16; Full bleed 393 x 268, radius 0. | Layout | Width | Radius | Outline | Lead column | | --- | --- | --- | --- | --- | | Inset | 361 | 16 | 1 pt on all four sides | 160 | | Full bleed | 393 | 0 | 1 pt on top and bottom only | 168 | Inset is a 393 pt screen less 16 pt of margin on each side. Inside a card, set the table radius to the card radius minus the card padding, so the corners stay concentric. Full bleed is for a table that meets the screen edge and scrolls sideways: its lead column sits on the 24 pt margin, which is why that column is 8 wider than in Inset. The Tasks table screen uses Full bleed. Both layouts measure 268 tall with four rows at Default density: a 44 header and four rows of 56. The outline is a stroke drawn inside the frame, so it takes no height. ## When should a column be pinned? Pin the column that names the row, so a value never loses its label while it scrolls. Pin one column only, and only when the table is wider than the screen. Specimen: Pinned column at rest, scrolled by 120. Lead column 160, scroll area 436, fade 40. | Part | Measure | What it does | | --- | --- | --- | | Pinned column | 160, from the table/column/lead token | Stays at the left edge, with a 1 pt right hairline in border/soft-100. | | Scroll area | Four columns, 436 wide | Amount 104, Status 132, Invoice 120 and Actions 80 slide under the pinned column. | | Peek | 201 of a 361 table | One full value column fits beside the pinned one and the next is cut, which invites the scroll. | | Scroll hint | 40 wide fade at the right edge | Fades to the table ground, 92 percent at 70 percent of its width, so more columns read as more. | | Edge shadow | dropShadow/edge | Falls on the values that pass under the pinned column once the table has scrolled. | | Show pinned column | Boolean, on by default | Turn it off when every column fits in one screen width. | A pinned column pays for itself when the table has more columns than fit beside it. On a 393 pt screen a 160 pt pinned column leaves 233 pt, a little under two value columns at the default width, so a table with three or more columns scrolls and gains from the pin. A table with a lead column and one value column fits without a pin, and the pin would only take 160 pt of width. ## Which density fits which screen? Use Default for most tables. Compact fits screens people scan row by row, and Comfortable fits cells that hold two lines or that fingers press. Specimen: Density Compact, Default, Comfortable. Rows 48, 56 and 64, padding 16, gap 8. | Density | Row height | Room above and below a 36 control | Use for | | --- | --- | --- | --- | | Compact | 48 | 6 | Long lists people scan, such as transactions. | | Default | 56 | 10 | Most tables, and the density the Table is built at. | | Comfortable | 64 | 14 | Cells with two lines, such as User, and tables people mostly tap. | Density is a property of _Table Cell, so the Table itself has none. To change a table, select its cells and set Density once. The header stays 44 at every density. ## Header and sort The header is one weak band. Only the sorted column carries a mark, so the eye finds the active sort without reading every label. Specimen: Sort None, Asc, Desc, Align Leading and Trailing. Header 44, padding 16, gap 4, sort mark 16. | Sort | Label | Mark | | --- | --- | --- | | None | text/soft-500, sm/default | None: the label stands alone. | | Asc | text/strong-950, sm/emphasized | chevron-up, 16 pt, in brand/base. | | Desc | text/strong-950, sm/emphasized | chevron-down, 16 pt, in brand/base. | A click cycles None, Asc, Desc and back to None, which the file wires as six prototype reactions at 120 ms on the standard easing. On hover and keyboard focus the header label takes the strong color. Align sets which edge the label sits on: Leading for words, Trailing for numbers, so a number column lines up under its header. Type Icon adds a 16 pt glyph before the label for the kind of data in the column, such as text, date, status or person. ## What can a Table cell hold? A cell holds one of eight parts, chosen through its Content swap. Each part hugs its content, so the cell does the aligning. Specimen: Text, Value, Status, Action, User, Trend, Sparkline, Slot. Cell 120 wide, padding 16, hairline 1. | Part | Use for | Size | Built from | | --- | --- | --- | --- | | _Cell Content / Text | Names, descriptions and any value that reads as words. | Hugs, 20 high | Label in fg/strong-950, sm/default | | _Cell Content / Value | A number. Right aligned so the digits line up down the column. | Hugs, 20 high | sm/emphasized in fg/strong-950 | | _Cell Content / Status | One word that names the status. | 24 high | Badge, Pill, Soft, with the Dot on | | _Cell Content / Action | One action. Put the rest behind a menu. | 36 round | Button, Neutral, Weak, Size sm, icon only | | _Cell Content / User | A row about a person: avatar, name and a second line. | 126 by 36 | Avatar at 24, name in sm/emphasized, second line in xs/default, fg/sub-700 | | _Cell Content / Trend | A change against a previous period. | 68 by 24 | Trend Chip | | _Cell Content / Sparkline | Shape only. The number belongs in its own column. | 64 by 20 | Sparkline, seven points | | _Cell Content / Slot | Anything the kit does not ship. | 120 by 24 | Frame on bg/weak-50 with a border/sub-200 stroke at radius 8 | Content is an instance swap with these eight parts as its preferred values, so adding a kind of cell costs one component and no extra variant. Cell contents use instance swap rather than native slots on purpose: Figma support confirmed on April 7, 2026 that once slot content is touched, even to reapply the same value, it stops inheriting library updates, and every filled table cell would freeze against the next Appetite UI release. ## How do you show a change where down is good? Set Direction to Down and Tone to Positive. Direction is what the number did, and Tone is whether that is good news: churn going up is Up and Negative, a falling cost is Down and Positive. Specimen: Direction Up, Down, Flat by Tone Positive, Negative, Neutral. Height 24, padding 4 by 8, gap 4, arrow 12. Trend Chip is 24 high with 4 by 8 of padding, a 12 pt arrow and the value in `xs/emphasized`. Positive and Negative sit on the lighter step of their state family with the `dark-950` step as ink, and Neutral sits on `bg/weak-50` with `fg/sub-700`. The arrow follows the number and the color follows the news, so a falling cost can be Down and Positive. The arrow is a picture and the tone is a color, so a screen reader needs the words: the live chip carries them as hidden text. A Sparkline colors by direction: Up is state/success/base-500, Down is state/error/base-500 and Flat is fg/sub-700. Beside a Trend Chip of the opposite tone it contradicts the chip, so pair a Sparkline with a number and let the chip carry the tone. ## When does a Key Value Row replace a table? When the data is one record. A Key Value Row is a label on the left and a value on the right, for summaries and detail lists. A table gives columns, this gives pairs. Specimen: Key Value Row, Divider on, last row without. 361 x 44, padding 12, divider 1. The row is 361 by 44 with 12 pt above and below. The label is `sm/default` in `fg/sub-700`, and the value is `sm/emphasized` in `fg/strong-950`. The divider is an absolute 1 pt layer in `border/soft-100`, because a layer can be switched by a component property and a stroke cannot: turn the Divider boolean off on the last row of a list. ## Properties Every property of the parts a table uses. Table has 2 layouts, _Table Header Cell is Align by Sort for 6 variants, _Table Cell is Align by Density for 6 variants and Trend Chip is Direction by Tone for 9 variants. | Set | Property | Type | Options | Default | | --- | --- | --- | --- | --- | | Table | `Layout` | Variant | Inset or Full bleed | Inset | | Table | `Show pinned column` | Boolean | On or off | On | | Table | `Show actions column` | Boolean | On or off | On | | Table | `Row 3` | Boolean | On or off | On | | Table | `Row 4` | Boolean | On or off | On | | _Table Header Cell | `Align` | Variant | Leading or Trailing | Leading | | _Table Header Cell | `Sort` | Variant | None, Asc or Desc | None | | _Table Header Cell | `Label` | Text | Any text | Column | | _Table Header Cell | `Type Icon` | Boolean | On or off | Off | | _Table Header Cell | `Type Icon Swap` | Instance swap | The Icons set | type | | _Table Cell | `Align` | Variant | Leading or Trailing | Leading | | _Table Cell | `Density` | Variant | Compact, Default or Comfortable | Compact | | _Table Cell | `Content` | Instance swap | The eight _Cell Content parts | _Cell Content / Text | | Trend Chip | `Direction` | Variant | Up, Down or Flat | Up | | Trend Chip | `Tone` | Variant | Positive, Negative or Neutral | Positive | | Trend Chip | `Value` | Text | Any text | 12.4% | | Key Value Row | `Label` | Text | Any text | Subtotal | | Key Value Row | `Value` | Text | Any text | 1,248.00 | | Key Value Row | `Divider` | Boolean | On or off | On | | Sparkline, on the Chart page | `Trend` | Variant | Up, Down or Flat | Up | | Sparkline, on the Chart page | `Show Dot` | Boolean | On or off | On | Row 3 and Row 4 take the table from four rows down to two. _Table Cell opens on Density Compact, while the Table is built from Default cells. Read from the Table page of the Figma file on October 2, 2026. ## Tokens Every value the Table parts read, resolved through its aliases to the Foundations primitive. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/white-0` | #FFFFFF | #0E0E0F | Table ground, body cells, the pinned column | | `bg/weak-50` | #F4F5F5 | #242427 | Header band, Neutral Trend Chip, Action button, Slot | | `border/soft-100` | #E9E9EA | #2F2F31 | Outline, row hairline, pinned hairline, Divider | | `border/sub-200` | #D1D1D6 | #48484A | Slot stroke | | `text/soft-500` | #8E8E93 | #AEAEB2 | Header label at Sort None | | `text/strong-950` | #0E0E0F | #FFFFFF | Header label when sorted | | `fg/strong-950` | #0E0E0F | #FFFFFF | Cell text, values, names, Key Value Row value | | `fg/sub-700` | #48484A | #C7C7CC | Second line of User, Key Value Row label, Neutral Trend Chip, Flat Sparkline | | `brand/base` | #155DFC | #2B7FFF | Sort chevron | | `state/success/lighter-50` | #F0FDF4 | #22C55E at 16% | Positive Trend Chip, Success status | | `state/success/dark-950` | #09361B | #86EFAC | Ink on the Positive chip and the Success status | | `state/success/base-500` | #22C55E | #16A34A | Status dot, Sparkline Up | | `state/error/lighter-50` | #FEF2F2 | #FB2C36 at 16% | Negative Trend Chip, Error status | | `state/error/dark-950` | #460809 | #FFA2A2 | Ink on the Negative chip and the Error status | | `state/error/base-500` | #FB2C36 | #FB2C36 | Sparkline Down | | Token | Value | Applied to | | --- | --- | --- | | `table/column/lead` | 160 | The pinned column | | `table/column/default` | 120 | A value column | | `table/column/action` | 80 | The Actions column | | `dimensions/spacing/4` | 16 | Cell and header padding at the sides | | `dimensions/spacing/2` | 8 | Gap inside a cell | | `dimensions/spacing/1` | 4 | Gap inside a header cell | | `dimensions/radius/xl` | 16 | Inset outline | | `dimensions/radius/md` | 8 | Slot cell | | `dropShadow/edge` | 6 0 12, spread -4, black at 8% | Pinned column edge, drawn once the table scrolls | | `sm/default`, `sm/emphasized` | 14 on 20, Regular and Semi Bold | Labels, values, names | | `xs/default`, `xs/emphasized` | 12 on 16, Regular and Semi Bold | Second line of User, Trend Chip, Status | Only the lead, default and action widths are tokens. Column / Amount is 104 wide and Column / Status is 132 wide in the Table, with no width variable behind either. ## How does Table differ on iOS and Material 3? Table has no counterpart on the Apple or Material 3 pages of the file, so Appetite UI draws one Table that is the same on both platforms. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Table | None in the file. The nearest pattern is List. | None in the file. The nearest pattern is List. | A platform list holds one value per row. Table keeps columns, pins one and scrolls the rest. | | Key Value Row | None in the file. A List row with a detail value comes closest. | None in the file. A List row with trailing text comes closest. | Key Value Row is a pair with a divider layer, built for summaries. | | Trend Chip | None in the file | None in the file | Neither platform page carries a change indicator. | ## Keyboard and screen readers A table that scrolls sideways has to take focus, and every part of it needs a name. The Table specimen on this page does all of it. | Part | Role and name | Keyboard | | --- | --- | --- | | Table | A table with a caption. Header cells are th with scope col, the first cell of each row is th with scope row. | Reads by row and column in a screen reader's table mode. | | Scroll region | A region with a name that says it scrolls sideways, in the tab order. | Tab to it, then the arrow keys scroll. | | Sort header | A button inside the th, with aria-sort on the sorted column only. | Enter or Space cycles None, Ascending, Descending. A polite status line says how the rows were sorted. | | Action | An icon button named with its row, such as Actions for Ines Roca. | Tab, then Enter or Space. | | Status | The word is the status, and color repeats it. | Not focusable. | | Trend Chip | Hidden text states the direction and the tone before the value. | Not focusable. | The Action control is 36 pt. The Platform collection sets `platform/min-touch-target` to 44 on iOS and 48 on Android, so give the control a transparent hit area of 44 pt: a 48 pt Compact row has room for it, and an Android build needs 48. The header label at Sort None is `text/soft-500` on `bg/weak-50`, a contrast of 2.99 to 1 in light and 7.0 to 1 in dark. The same soft text color on white is 3.26 to 1. Light mode is under 4.5 to 1 for 14 pt text and is a documented product choice. Give a header label in your own product a color at 4.5 to 1, such as text/sub-700. ## Guidelines - Do: Align numbers to the trailing edge in Value cells, so the digits line up down the column. - Avoid: Do not left align numbers. Digits of different lengths stop lining up and the column cannot be compared. - Do: Put one word in a Status cell and let the dot and the tint repeat it. - Avoid: Do not put a sentence in a Status cell. It truncates and the badge stops reading as a state. Pin the one column that names the row and keep every other column in the scroll area. Keep one row height across the table, and keep one action per row with the rest behind a menu. Set a Trend Chip from direction first and tone second. ## Examples Three tables made of the parts above, with the rows the Figma file ships: the invoices of the Table set, the tasks of the Tasks table screen in Full bleed, and the top sellers of the Examples board. Specimen: Invoices, Layout Inset. Inset 361, Full bleed 393, Density Default. Specimen: Tasks, Layout Full bleed, Type Icon on. Inset 361, Full bleed 393, Density Default. Specimen: Top sellers, Layout Inset, Sparkline and Trend Chip columns. Inset 361, Full bleed 393, Density Default. The tasks table sorts by Due, so its header carries the one mark. Top sellers sorts by Sales, descending, and puts a Sparkline and a Trend Chip beside the number: scroll it sideways to reach the Trend column. Rows from the Table set, the Tasks Table screen and the Table Examples board, read on October 2, 2026. --- --- title: Toast description: Toast reports what just happened without blocking the screen, then leaves on its own. Appetite UI Figma component: two types, five states, tokens. group: Components source: https://www.appetiteui.com/docs/toast dateModified: 2026-10-03 --- # Toast Updated: October 3, 2026. Toast reports what just happened without blocking the screen, then takes itself away. ## Preview Transient feedback that does not block input and takes itself away. On Android this is a Snackbar, on iOS a custom overlay. Specimen: Type Line at State Neutral, then Type Long at State Success. 320 wide, 36 and 96 tall, radius 24, dropShadow/sm. Both types are the same card. Line is one row with a title, a link action and a dismiss. Long adds a description under the title and stacks the two controls on the right. Long is 96 tall, with the description wrapped to two lines. The link reads View, and the surface is bg/raised, the token for floating surfaces: white in light, one step lifted in dark. Toast ships ten variants, Type by State. Source: Figma set Toast, read October 2, 2026. ## Which types does Toast have? Two: Line and Long, two shapes for two amounts of message. The type scale changes with them. Specimen: Type Line then Type Long, both at State Neutral. icon 16 and 20, title 12/16 and 14/20. The two differ in more than height. Line sets the title at 12/16 next to a 16 icon at stroke 1.5. Long lifts it to 14/20 next to a 20 icon at stroke 1.75 and lets the description run to two lines, which takes the card to 96. Both titles are Regular. ## Which states does Toast have? Five: Neutral, Error, Success, Warning and Info, each with its own icon. State changes the icon and its color and nothing else. Specimen: Neutral, Error, Success, Warning and Info, at Type Line. the card stays bg/raised in all five, the icon changes. Every state has its own icon: Neutral message-circle, Info info, Error circle-alert, Success circle-check-big and Warning triangle-alert. The surface never changes: no tint, no colored border, only the icon. Info holds #155DFC in both themes while the link beside it moves to #2B7FFF, so two blues that match in light come apart in dark. The dismiss x is `fg/soft-500`, #8E8E93, a documented product choice that measures 3.26:1 on a white card, above the 3:1 an icon needs. The Success icon is 2.28:1 on white, so the title must name the state and the icon never carries it alone. In dark the View link is #2B7FFF on #242427 at 4.11:1, under the 4.5:1 that WCAG asks of small text. In code, announce a toast in a polite live region, keep it on screen long enough to read, and pause its timer while it has focus or a pointer over it. ## Properties Two variant axes, then three booleans and two text properties. | Property | Type | Default | | --- | --- | --- | | `Type` | Variant: Long \| Line | Long | | `State` | Variant: Neutral \| Error \| Success \| Warning \| Info | Neutral | | `Icon` | Boolean | true | | `Link Button` | Boolean | true | | `Dismiss Icon` | Boolean | true | | `Title Edit` | Text | Title of toast | | `Description` | Text | A short line that confirms what just happened. | | Part | What it is | Size | | --- | --- | --- | | `Button` | A Button instance, Brand Link sm, label View | 71 x 36 | | `Compact Button` | Transparent, holding an x | 32 x 32 | Description is a property on both types even though only Long draws it, so setting it on a Line toast changes nothing. There is no Icon Swap property: the icon belongs to the State, and a different one means swapping the nested icon instance. The Button instance is exposed, so its label is edited from the Toast. There is no position, stacking or duration: where it sits, how long it stays and what a second arrival does are yours. ## Tokens Four for the card, one for the action and five for the icon. Two of the five do not theme. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/raised` | #FFFFFF | #242427 | The card, all ten variants | | `border/soft-100` | #E9E9EA | #2F2F31 | 1px inside border | | `text/strong-950` | #0E0E0F | #FFFFFF | Title | | `text/sub-700` | #48484A | #C7C7CC | Description, Long only | | `brand/base` | #155DFC | #2B7FFF | Action label | | `fg/soft-500` | #8E8E93 | #AEAEB2 | Dismiss x | | `state/faded/base-500` | #8E8E93 | #636366 | Neutral icon | | `state/error/base-500` | #FB2C36 | #FB2C36 | Error icon | | `state/success/base-500` | #22C55E | #16A34A | Success icon | | `state/warning/base-500` | #FF6900 | #F54900 | Warning icon | | `state/information/base-500` | #155DFC | #155DFC | Info icon, one value in both modes | Radius is `dimensions/radius/2xl` at 24 on the card and `dimensions/radius/full` on the link and the dismiss. The shadow is the effect style `dropShadow/sm`. Warning, success and faded step from their 500 to their 600 in dark, which keeps them off a dark card. Error and information do not move, so on the dark card information is the weakest color here, sitting next to a link that moved the other way. ## How does Toast differ on iOS and Material 3? iOS has no toast, so the file has no iOS set for it. Material 3 has the Snackbar, a 344 wide bar with a 4 radius, and Appetite UI Toast is the same idea as a 320 wide card with a 24 radius. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Toast | None in the file. The set description names a custom overlay. | M3 / Snackbar: Configuration Text only, Text and action, Text and longer action, by Option One line or Two lines, with an optional close affordance. 344 wide, 48, 68 or 112 tall, radius 4. | Appetite UI is 320 wide at radius 24 and has five States with their own icon, which a Snackbar does not. The Appetite UI action is a Brand Link button. | The link button is 36 high and the dismiss is 32, both under the minimum touch target of 44 pt on iOS and 48 dp on Android, which comes from `platform/min-touch-target` in the Platform collection. Give both a larger hit area in code. The Motion table enters a toast on `motion/toast/enter`: 120 ms on a decelerate curve, or a spring with response .30 and damping .90. ## Guidelines - Do: Keep the action optional. Undo, View, Retry: things the user can ignore and lose nothing by, because the toast is going to leave on its own. - Avoid: Never put a required action in a toast. It dismisses itself, so a Confirm that lives only here is a decision the user can miss by looking away. Use it for feedback about something that already happened, not for a question. Keep the title to one line, and reach for Long only when the extra sentence changes what the user would do. Put a required decision in a Modal or an Alert, never here. --- --- title: Toggle description: Toggle turns one setting on or off and applies it at once. Appetite UI Figma component: four states with a focus ring, label rules and tokens. group: Components source: https://www.appetiteui.com/docs/toggle dateModified: 2026-10-03 --- # Toggle Updated: October 3, 2026. Toggle turns a single setting on or off, and applies the change immediately. ## Preview Default, active. A 44 by 28 track with a 22 pt handle, centered in a 52 by 44 frame, so the thing you can hit is bigger than the thing you can see. Click it. Specimen: State Default, Active True. Frame 52 x 44, track 44 x 28, radius 9999, 22 px handle, 16 px of travel. The 52 by 44 frame is the target and the control inside it is 44 by 28, sitting 4 from each side and 8 from the top and bottom. The handle is a 22 circle inset 3, so it sits at 3 when off and 19 when on, 16 of travel. Two shadows sit under it, both black, one at 4 percent and one at 1. Source: the Toggle set of the Appetite UI Figma file, read on October 2, 2026. ## Which states does Toggle have? Four: Default, Pressed, Focused and Disabled, each off or on. The file has no Hover state, because a finger does not hover, so a pointer hover moves these specimens toward Pressed. Pressed shifts the track while the finger is down, and Focused draws the ring for keyboard and switch control. Specimen: State x Active. Default, Pressed, Focused, Disabled, each off then on. Focused is the focusRing/brand effect style, a 2 pt gap in the surface color and then a 2 pt ring in brand/base, drawn around the track. The frame is 52 by 44 so the ring has room. Pressed moves each fill one step along its own ramp: bg/sub-200 when off, brand/pressed when on. Disabled off is bg/soft-100 with no handle shadow. Disabled on keeps brand/base at 40 percent opacity, so a disabled switch still shows which way it is set. Eight variants, State by Active, no holes. Source: component set 216:449 of the Appetite UI Figma file, read on October 2, 2026. ## Label The label is its own component, so the track stays a track. Align puts it on either side, and the description can be switched off. Each row is one switch: click the text or the track. Specimen: Align Left, Align Right. 340 x 48, gap 16, title 18/28, description 14/20. The row is 340 by 48: the 52 wide Toggle, 16 of gap, then 272 of text. The height comes from the text, 28 for the title plus 20 for the description at 14/20, so switching Show Description off takes the row to 44, the height of the Toggle frame. Align swaps the order of the two children. ## Properties Two component sets: Toggle, the track, and _Toggle Label, the row that carries it. | Property | Type | Default | | --- | --- | --- | | `State` | Default \| Pressed \| Disabled \| Focused | Default | | `Active` | True \| False | False | | `Align` | Left \| Right | Left | | `Show Description` | Boolean | true | | `Label` | Text | Label | | `Description` | Text | Get a push when the order ships | Toggle is eight variants of State by Active and carries no text. _Toggle Label is two variants of Align and holds Label, Description and Show Description. The underscore keeps _Toggle Label out of the published library, so copy the row from the Toggle page of the file when you need it. ## Tokens Every value the toggle reads, resolved through its aliases to the primitive underneath. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/soft-100` | #E9E9EA | #48484A | Track when off, Disabled and off | | `bg/sub-200` | #D1D1D6 | #636366 | Track pressed while off | | `brand/base` | #155DFC | #2B7FFF | Track when on, at 40% when Disabled | | `brand/pressed` | #193CB8 | #155DFC | Track pressed while on | | `static/static-white-0` | #FFFFFF | #FFFFFF | Handle | | `focusRing/brand` | 2 pt `bg/white-0`, then 2 pt `brand/base` | 2 pt `bg/white-0`, then 2 pt `brand/base` | Focused, on the track | | `text/strong-950` | #0E0E0F | #FFFFFF | Label title | | `text/sub-700` | #48484A | #C7C7CC | Label description | bg/sub-200 is the next step along the gray ramp and brand/pressed is a step darker than brand/base in both modes, so pressing moves the control forward. The handle reads static/static-white-0, so it stays white in dark mode. ## How does Toggle differ on iOS and Material 3? Appetite UI Toggle keeps one shape on both platforms: a 44 by 28 track in a 52 by 44 frame. The native switches live on the iOS and Material 3 pages of the file. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Toggle | iOS / Toggle, 64 by 28, State Idle and Pressed by Is On by Is Enabled | M3 / Switch, 52 by 32, Selected by Is Enabled | The iOS track is 20 wider than Appetite UI and the Material 3 track is 8 wider and 4 taller. Neither native set has a Focused state. | The minimum touch target is 44 pt on iOS and 48 dp on Material 3, set by `platform/min-touch-target` in the Platform collection. The 52 by 44 frame meets the iOS minimum on both axes. On Android, add 4 dp of hit area in code. ## Guidelines - Do: Name the setting, then say what it does. A toggle takes effect the moment it moves, so there is nothing to save and nothing to confirm. - Avoid: Never label a toggle with a negative. Off then means on, and the reader has to solve a puzzle before changing a setting. If a change needs a Save step, use Checkbox instead. A toggle names a state, so Weekly digest is right and Turn on weekly digest is not. Make the whole label row tappable in code, because the file draws only the 52 by 44 frame as the target. --- --- title: Toolbar description: Toolbar holds the actions for the current screen at its bottom edge: two to four icon actions and an optional primary. Appetite UI component for Figma. group: Components source: https://www.appetiteui.com/docs/toolbar dateModified: 2026-10-03 --- # Toolbar Updated: October 3, 2026. Toolbar holds the actions for the current screen, anchored to the bottom of it. Two to four icon actions, and one filled primary when the screen has a next step. ## Preview Actions for the current screen, anchored to the bottom. Two to four, plus an optional primary. Specimen: Actions 2 with Primary False, then Actions 4 with Primary True. 340 x 62, radius 0, a 1px border on the top edge only. The only stroke runs along the top and the corners are square, because this is the bottom edge of a screen. Icons sit on the left and the right holds a filled primary, or nothing. A toolbar changes with the screen, and Navigation stays the same across screens. ## How many actions can a Toolbar hold? Two, three or four icon actions. Without a primary they spread across the full width of the bar. Specimen: Actions 2, then 3, then 4, all at Primary False. buttons 44 square, icons spread over 324 without a primary. Without a primary action the icons spread across the whole bar, over the 324 inside its padding. The icons ship in a fixed order, share-2, bookmark, folder and trash-2, and each Button takes its own icon, so replace them with yours. The buttons are Neutral Link, Icon Only, which means no fill and no border: the 44 square is a target with no visible shape. ## Can a Toolbar have a primary action? Yes, one filled action on the right, or none. With a primary the icons stay together on the left and the plus sits at the end. Specimen: Primary False then Primary True, both at Actions 4. hugging row 188, primary 44 square at x 288, else spread over 324. The primary is the only filled thing on the bar, and on Android it is the FAB. It is a Button, so Pressed and Focused come from [Button](https://www.appetiteui.com/docs/button): press an icon in the specimen to see the pressed fill, and tab to one to see the focus ring. ## How does Toolbar differ on iOS and Material 3? Toolbar is one flat bar for both platforms. The Apple pages draw the iOS toolbar as glass groups, and the Material 3 pages in the file have no bottom bar. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Toolbar, 340 x 62, Actions 2 to 4 | iOS / Toolbar, a floating glass bar of icon groups, Items 2 to 5 | Bottom app bar with a floating action button, not drawn in the file | Appetite UI is a flat bar with a top hairline and square corners. iOS floats the actions on glass. The Appetite UI primary is the Material FAB | | Primary, 44 | The trailing group of the iOS toolbar | Floating action button | Appetite UI keeps the primary inside the bar | The minimum touch target is 44 on iOS and 48 on Android, from `platform/min-touch-target`. Every button on the bar is 44, so it meets the iOS minimum and sits 4 under the Android one. For a Compose build, pad each hit area to 48 and keep the drawn button at 44. In code the bar is a BottomAppBar on Android, with the primary as its FAB. See [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge). The vertical Duo toolbar is on the [iOS page](https://www.appetiteui.com/docs/ios). ## Properties Two axes and six variants. The icons are the ones inside each Button. | Property | Type | Default | | --- | --- | --- | | `Actions` | 2 \| 3 \| 4 | 2 | | `Primary` | False \| True | False | | Part | What it is | Size | | --- | --- | --- | | `Actions` | A row at x 8, gap 4 with a primary, spread over the bar without one | 92, 140 or 188, or 324 spread | | `Button`, action | Button instance, Neutral Link md, Icon Only | 44 x 44 | | `Button`, primary | Button instance, Brand Filled md, Icon Only | 44 x 44 | Each variant holds as many action buttons as its Actions value, plus the primary where Primary is True, and the buttons are the only layers that carry an icon. The bar has no states of its own, only the Button presses inside it, and no label variant, so it is icon only. Build an unavailable action yourself with the Disabled state of Button. ## Tokens Five colors. No shadow, no radius, no elevation. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/white-0` | #FFFFFF | #0E0E0F | The bar | | `border/soft-100` | #E9E9EA | #2F2F31 | The top edge, 1px inside | | `fg/sub-700` | #48484A | #C7C7CC | Action icons | | `brand/base` | #155DFC | #2B7FFF | Primary fill | | `static/static-white-0` | #FFFFFF | #FFFFFF | The plus, one value in both modes | The bar is welded to the bottom of the screen, and the top hairline is its only separation from the content above. On iOS it sits over the home indicator and the SDK takes over with Liquid Glass, so treat the flat fill as a placeholder for that material. ## When should I use a Toolbar? Use it for actions on the current screen, and move it out of the way when that screen changes. - Do: One filled button, on the right, doing the thing this screen is for. Everything to the left of it is a supporting action on the same content. - Avoid: Do not fill a second button. Two filled circles is two primaries, and the bar stops telling anyone what the next step is. Section links belong in [Navigation](https://www.appetiteui.com/docs/navigation). Four actions is the ceiling, so put the overflow in a [Context Menu](https://www.appetiteui.com/docs/context-menu) behind an ellipsis. Keep the destructive action away from the primary. --- --- title: Tooltip description: A tooltip names one control in a few words, anchored to the thing it describes. Appetite UI Figma component: four positions, two anchor sizes, tokens. group: Components source: https://www.appetiteui.com/docs/tooltip dateModified: 2026-10-03 --- # Tooltip Updated: October 3, 2026. Tooltip explains one control in a few words, anchored to the thing it describes. There is no hover on a phone, so it opens on tap or focus. ## Preview A short hint anchored to the control it explains. No hover on a phone: it opens on tap, closes on the next. Keep it to a label and a line. Anything longer belongs in the screen, not over it. Specimen: Open True, Position Top, Size md, tap the icon. anchor 24, bubble 146 x 48, radius 12, padding 8 12. The component's own box is the 24 icon. The bubble sits outside that frame in the file and is absolute here, so opening one never moves anything around it. The bubble hugs its two strings, which are the file's sample copy: 146 wide and 48 tall. Open False draws the anchor alone in fg/soft-500, and it is the default in the file. Open True lights the anchor in fg/sub-700 and adds the bubble. Source: Figma sets Tooltip and _Tooltip, read October 2, 2026. ## Where does a Tooltip open? Top, Bottom, Left or Right: four positions on one axis. The bubble clears the anchor by 8 on the side it points from and centers on the other. Nothing flips at a screen edge, so pick the side with room. Specimen: Top, Bottom, Left, Right. 8 gap on the pointing side, pointer 16 x 8. The bubble is the same 146 wide in every position because it hugs the same two strings. The file's blocks measure 146 by 56 at Top and Bottom and 154 by 48 at Left and Right once the 8 deep pointer is counted. The width follows the text and stays the same as the position changes. ## Which sizes does Tooltip come in? Two, md and sm. The axis moves the anchor only, so the bubble is the same object at both and the size sets the tap target. Specimen: Size md then sm, both Open True. icon 24 and 16, bubble unchanged at 146 x 48. A 16 anchor is under the minimum touch target of 44 pt on iOS and 48 dp on Android, which comes from `platform/min-touch-target` in the Platform collection, and the 24 anchor at md is under it too. Give the icon a larger tap target than the artwork, or hang the tooltip off a control that already has one. ## Content Two booleans on the bubble, both true by default. Turn the supporting line off for a one word label. Turn the headline off and you get a sentence in the muted color, the weaker of the two. Specimen: Both, Headline only, Supporting Text only. each line 12/16, one line drops the box to 32 tall. The wrapper hugs its content, so dropping a line takes 16 off the height and leaves the width to the longer line that remains. The headline is the only line with weight: white on the fill in Semi Bold, while the supporting line reads Regular in a muted gray. ## Properties Three variant axes on the published component. The bubble is a private block with two booleans of its own. | Property | Type | Default | | --- | --- | --- | | `Open` | Variant: True \| False | False | | `Position` | Variant: Top \| Left \| Right \| Bottom | Top | | `Size` | Variant: md \| sm | md | | `Headline` | Boolean, on _Tooltip | true | | `Supporting Text` | Boolean, on _Tooltip | true | | Set | Variants | Size | | --- | --- | --- | | `Tooltip` | 16, Open x Position x Size | 24 x 24, or 16 x 16 at sm | | `_Tooltip` | 4, on Position | 146 x 56 at Top and Bottom, 154 x 48 at Left and Right | There is no text property anywhere. Both strings are plain text nodes, so real copy is an override on each instance. The published component measures the anchor only. A tooltip never changes the layout it sits in, and nothing stops it running off a narrow screen. ## Tokens Five colors, and two of them invert with the theme. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `bg/strong-950` | #0E0E0F | #FFFFFF | The bubble and its pointer | | `text/white-0` | #FFFFFF | #0E0E0F | Headline | | `text/disabled-400` | #AEAEB2 | #8E8E93 | Supporting line | | `fg/sub-700` | #48484A | #C7C7CC | The anchor, Open True | | `fg/soft-500` | #8E8E93 | #AEAEB2 | The anchor, Open False | The supporting line reads `text/disabled-400`, the muted color the file gives it. Geometry runs on `dimensions/radius/lg` 12, `dimensions/spacing/3` 12, `dimensions/spacing/2` 8 and `dimensions/icon/stroke` 2. The bubble carries no effect style, so a layer floating over content has only its own fill to separate it. ## How does Tooltip differ on iOS and Material 3? iOS has no tooltip set in the file, and a phone has no hover. Material 3 has two, a Plain Tooltip for a label and a Rich Tooltip for a title, text and action, where Appetite UI Tooltip is a headline over one supporting line. | Appetite UI | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Tooltip | None in the file. | M3 / Plain Tooltip, Type Single line or Multi line, 24 tall at radius 4. M3 / Rich Tooltip, 312 by 136. | Appetite UI draws a 48 tall bubble at radius 12 with a 16 by 8 pointer and four positions, and the anchor is part of the component. | The set description says to use it sparingly on mobile. The _Tooltip description says the bubble is raised on tap or focus, so draw the focus state too and let a keyboard reader get the hint a touch reader gets. ## Guidelines - Do: Define one term the screen cannot. A label and a line, and the answer is on the screen the moment the user asks. - Avoid: Do not put an action in it. A tooltip closes on the next tap anywhere, so anything you can press inside one is a target the user loses on the way to it. Use it where a control cannot say what it means in the space it has: an icon button, a metric, a legal term. Never hide anything the user needs to finish the task, because on a phone a tooltip takes a deliberate tap. Check the side before you ship. Nothing flips away from a screen edge, so a Left tooltip near the left margin runs off the screen. --- --- title: Top Bars description: Top Bar is the header at the top of a mobile screen: title, back button and up to two actions, in three sizes. Figma component for iOS and Android. group: Components source: https://www.appetiteui.com/docs/top-bars dateModified: 2026-10-03 --- # Top Bars Updated: October 3, 2026. The header at the top of a screen: where you are, how to get back, and at most a couple of things to do here. Size sm is for pushed screens, md for the root screen of a tab, lg for a screen whose title is the point. ## Preview A screen header with a title, a caption, a back button and up to two actions. On iOS it maps to the NavigationStack toolbar, on Android to a TopAppBar. Specimen: Size sm, Actions False, Show Caption and Show Back Chevron true. 340 x 64, padding 0 24, gap 12, back button 44. The back button is a white raised circle with a hairline and dropShadow/xs. The two secondary actions share one capsule. The bar has no fill of its own until Glass is turned on, so it sits on whatever is behind it. The title block takes what the actions leave, 236 here. ## How tall is a Top Bar? Sm and md bars are 64 tall and lg is 132. Sm keeps the title on the back button's row at 20. Md is the same bar with a 24 title. Lg gives a 30 title its own row underneath, the pattern that collapses into sm as the user scrolls. Specimen: Size sm, md, then lg, all Actions False. sm and md 64 in one row, lg 132 as a 60 nav row over a 72 title block. Size md is for the root screen of a tab, the first thing someone sees when they switch tabs. The title takes the page title size, 24, on the bar's row, and pushed screens use sm. A root screen has nowhere to go back to, so switch Show Back Chevron off there, and Show Caption too when the title says enough. Specimen: Size md on a tab root, Show Back Chevron and Show Caption false. 340 x 64, title 24/32 inline, no back button and no caption. Each size has its own type pairing. The title is 20 Semi Bold at sm, 24 Semi Bold at md and 30 Medium at lg, and the lg title row is 72 tall with the caption at 14. Titles at 24 and above are set in the heading face, Inter Display. ## Which actions can a Top Bar hold? Three options on one axis: nothing, one filled button for what this screen is for, or up to two quiet ones in one capsule. The title block shrinks to make room, so a long title truncates sooner. Specimen: Actions False, Main Button, Secondary Actions. title block 236, then 180, then 136. Main Button is a brand circle with a white check. Secondary Actions is one 88 wide capsule holding two 44 circles, raised like the back button, so the pair reads as one control. Two is the ceiling the component ships, because a third would eat the title. Every circle on the bar is a Button instance, so Pressed, Focused and Disabled behave as on [Button](https://www.appetiteui.com/docs/button). Press a circle in the specimen to see the pressed fill, and tab to one to see the focus ring. ## When should I turn Glass on? Turn it on when the bar floats over scrolling content that must stay readable underneath. Glass is one boolean, off by default, and on a plain background it blurs nothing. Specimen: Glass true, over a hatch so there is something to see through. bg/glass at 72 percent in light and 55 in dark, under a 16 blur. Glass is drawn with the Appetite UI effect style backdropBlur/md under the bg/glass fill, a blur of 16, so the bar renders the same in Figma and on the web. ## What is Section Header? Section Header is a separate component for headers inside a screen: a title over a block of content with one optional link. Use it to break a long screen into groups the eye can scan. Specimen: Section Header, Link true then false. 340 wide, title 18/28 Semi Bold, link 36 tall. The title runs 18 on a 28 line and the link is 36 tall, which is the height of the row. ## How does Top Bar differ on iOS and Material 3? Top Bar is one header for both platforms: a back button, a title and up to two actions. Material 3 has its own top app bar, and the Apple pages draw no navigation bar, only the bottom iOS / Toolbar. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | Top Bar, sm and md at 64, lg at 132 | NavigationStack navigation bar. The Apple pages draw no navigation bar set: iOS / Toolbar there is the bottom toolbar | M3 / Top app bar: Small 64, Medium 112, Large 152 | Appetite UI has three sizes and the same layout on both platforms. Material has four bar types, including Center-aligned | | Back button, 44 | Back button in the navigation bar | Navigation icon in the top app bar | Appetite UI draws a raised white circle, the platform bars draw a plain glyph | | Section Header | Section header in a List | List subheader | Appetite UI adds one optional link, See all, at the end of the row | The minimum touch target is 44 on iOS and 48 on Android, from `platform/min-touch-target`. Every circle on the bar is 44, so it meets the iOS minimum and sits 4 under the Android one. For a Compose build, pad each hit area to 48 and keep the drawn circle at 44. See [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge) and the [Material 3 page](https://www.appetiteui.com/docs/material-3). ## Properties Two variant axes and five instance properties on Top Bar. Section Header is its own component with two. | Property | Type | Default | | --- | --- | --- | | `Size` | lg \| sm \| md | lg | | `Actions` | False \| Main Button \| Secondary Actions | False | | `Title`, `Caption Text` | Text | Title, Caption | | `Show Caption` | Boolean | true | | `Show Back Chevron` | Boolean | true | | `Glass` | Boolean | false | | `Section Title`, `Link` | Text, Boolean, on Section Header | Section title, true | | Component | Variants | Size | | --- | --- | --- | | `Top Bar` | nine, Size crossed with Actions | 340 x 64 at sm and md, 340 x 132 at lg | | `Section Header` | not a set | 340 x 36 | A real header is this component plus whatever the platform draws above it, such as the status bar. Top Bar has no search field of its own. ## Tokens Every value the two components read, resolved to the primitive underneath. | Token | Light | Dark | Applied to | | --- | --- | --- | --- | | `text/strong-950` | #0E0E0F | #FFFFFF | Title, and the Section Header title | | `text/soft-500` | #8E8E93 | #AEAEB2 | Caption | | `bg/raised` | #FFFFFF | #242427 | Back circle and the secondary capsule | | `border/soft-100` | #E9E9EA | #2F2F31 | The hairline round both | | `fg/sub-700` | #48484A | #C7C7CC | Back chevron and the secondary glyphs | | `brand/base` | #155DFC | #2B7FFF | Main button fill, the section link | | `static/static-white-0` | #FFFFFF | #FFFFFF | The check on the main button | | `bg/glass` | #FFFFFF at 72% | #242426 at 55% | Background, shown when Glass is true | | Effect style | Value | Applied to | | --- | --- | --- | | `dropShadow/xs` | 0 1 2 at 4% black, then 0 4 4 at 1% black | Back circle and the secondary capsule | | `backdropBlur/md` | Background blur 16 | Background, shown when Glass is true | Every glyph is drawn at 22. Geometry runs on `spacing/16` 64, `spacing/11` 44, `spacing/6` 24, `spacing/4` 16, `spacing/3` 12, `spacing/2` 8 and `spacing/1` 4. The caption uses the product soft text color, which measures 3.26:1 on white and is a documented product choice. Raise it in your own product if the caption carries essential information. Every circle on the bar is a Button, so in code it takes keyboard focus and shows the focus ring, and an icon-only circle needs an accessible name such as Back. ## Which size should I use? Use md on the root screen of a tab, sm on every screen pushed from it, and lg where the screen is a destination and the title is worth the room. - Do: Name the screen in the title and put the qualifier in the caption. One filled button for the one thing this screen exists to finish. - Avoid: Do not write a sentence into a block that is 136 wide once two actions are in. It truncates in the middle and the half that survives is the half nobody needed. Keep the back button on pushed screens: on Android hardware without a back key it is the only way out. Decide the actions before the title, because the title block is what they leave. --- --- title: Onboarding description: Onboarding screens for iOS in Figma, light and dark: welcome, two sign in layouts and sign up, built from Appetite UI components. group: App screens source: https://www.appetiteui.com/docs/screens-onboarding dateModified: 2026-10-03 --- # Onboarding Updated: October 3, 2026. A welcome screen, two sign in layouts and a sign up screen, drawn light and dark from components already in the library. Change Button or Text Input once and all 4 screens follow. ## Preview Welcome, Sign In with social buttons first, Sign In with the form first, and Sign Up. Together they take a new user from first launch to a signed in account. Specimen: Onboarding, four screens, light and dark. 393 x 852 each, Platform ios-md. | Screen | What it shows | Built from | | --- | --- | --- | | Welcome | A photograph with the logo on it, a headline, pagination dots and a way in or past | Status Bar, Logo, Pagination, Button | | Sign in, social first | Four round provider buttons above the email and password form | Logo, Social Button, Divider, Text Input, Button | | Sign in, form first | The form and a Sign in button, then Apple and Google as wide buttons | Logo, Text Input, Button, Divider, Social Button | | Sign up | Email, an optional phone number and a password with a hint, the Terms line and four provider buttons | Logo, Text Input, Button, Divider, Social Button | Each screen is drawn in Light and in Dark, with Color Tokens set on the frame itself. The dark screens are the same instances resolved against the other mode, so a rebrand in the variables moves both rows. Onboarding is also drawn for the outer and inner display of iPhone Duo, see [iPhone Duo screens](https://www.appetiteui.com/docs/screens-iphone-duo). Sign Up asks for consent to the Terms and the Privacy Policy, marks the phone number optional and shows a password hint. Welcome sets the logo straight on the photograph. ## How do the two Sign In layouts differ? Social first leads with four round provider buttons. Form first leads with the email and password fields. Social first puts four round Social Buttons directly under the headline and pins the Sign in button to the bottom edge, so the form sits in the middle of the screen. Form first starts with the email and password fields and a Sign in button right under them, and moves Apple and Google to two wide Social Buttons below an or divider. Both layouts are the same instances in a different order: one Logo, two Text Inputs, two Buttons and one Divider. Only the Social Buttons change, from 4 to 2. Switching a product from one layout to the other is a rearrangement, not a rebuild. | Layout | Order top to bottom | Social Buttons | Sign in button | | --- | --- | --- | --- | | Social first | Headline, four round Social Buttons, or divider, Email and Password, Sign in | 4, glyph only | Pinned to the bottom edge, above the Sign up link | | Form first | Headline, Email and Password, Sign in, or divider, Apple and Google | 2, with a label | Directly under the form | The minimum touch target on iOS is 44 pt. The frames pin Platform to ios-md, where `platform/min-touch-target` reads 44. The android mode of the same variable reads 48 dp. ## What are the Onboarding screens built from? 60 instances across the 4 screens. 36 are Appetite UI components, 9 are Lucide icons and 15 are logo, brand mark and flag assets. Every one of them reads from the same variables, which is why a rebrand moves all 4 screens at once. 37 instances sit directly on the frames and the rest sit inside them. Placed counts an instance that is not inside another instance. Nested counts one that is, which is where the three Pagination dots, every glyph and every brand mark live. A component is counted by its set name, so every Button variant is a Button, and an icon is an instance named in lowercase. The dark row holds the same instances as the light row. | Component | Placed | Nested | Where | | --- | --- | --- | --- | | [Social Button](https://www.appetiteui.com/docs/button#social) | 10 | 0 | Both sign in screens and Sign Up | | [Button](https://www.appetiteui.com/docs/button) | 8 | 0 | All four screens | | [Text Input](https://www.appetiteui.com/docs/input) | 7 | 0 | Both sign in screens and Sign Up | | [iOS / Status Bar](https://www.appetiteui.com/docs/ios) | 4 | 0 | All four screens | | [Logo](https://www.appetiteui.com/docs/assets) | 4 | 0 | All four screens | | [Divider](https://www.appetiteui.com/docs/divider) | 3 | 0 | Both sign in screens and Sign Up | | [Pagination](https://www.appetiteui.com/docs/pagination) | 1 | 3 | Welcome, carrying three dots | | [Lucide icons](https://www.appetiteui.com/docs/icons) | 0 | 9 | Mail, lock and eye-off in the Text Inputs of three screens | | [Assets](https://www.appetiteui.com/docs/assets) | 0 | 11 | Apple, Google, Facebook and X marks in the Social Buttons, and the flag in the Sign Up phone field | Three things on these screens are drawn by hand. Welcome carries the photograph as a 393 x 520 rectangle with an image fill, and a 393 x 180 rectangle named Top Background with a gradient fill over the top edge. Each Sign In screen carries a rectangle named Divider that works as a spacer, 345 x 147 on social first and 345 x 67 on form first. Counted on October 2, 2026 with a Plugin API script over the four light frames of the Onboarding page in the Appetite UI Figma file. ## Which tokens do the Onboarding screens use? Almost every solid fill and stroke on these frames resolves through a variable. The exceptions are brand colors, which are not tokens. The four light frames hold 131 solid fills and strokes that are bound, spread over 16 different variables. Another 32 solid paints are not bound: 12 in the Logo, 14 in the Social Button marks and 6 in the flag of the phone field, the colors of a brand and a flag. The Welcome gradient has two stops and neither is bound. The photograph is an image fill. | Token | Where it lands | Paints | | --- | --- | --- | | `text/soft-500` | Input labels, placeholders, the or label of a Divider and the consent line on Sign Up | 21 | | `fg/strong-950` | Status Bar glyphs and the X and Apple marks | 19 | | `border/soft-100` | Social Button outlines and the Divider rules | 16 | | `bg/white-0` | The screen frames and the Social Button fills | 13 | | `brand/base` | Filled Buttons, Skip for now, the active Pagination dot, Forgot password and the Sign up, Sign in, Terms and Privacy Policy links | 13 | | `static/static-white-0` | White on the photograph and on a filled Button: the Welcome status bar, Button labels, the Logo | 10 | | `fg/soft-500` | Input glyphs: mail, lock and eye-off | 9 | | `text/sub-700` | The supporting line under each headline and the account question before Sign up or Sign in | 8 | | `border/sub-200` | The Text Input underline | 7 | | `text/strong-950` | Headlines and the entered text | 5 | | `colors/blue/500` | The blue tile of the Logo, a Foundations primitive bound directly | 4 | | `colors/alpha/gray/alpha-16` | The two inactive Pagination dots, a Foundations primitive bound directly | 2 | | `bg/strong-950`, `fg/white-0`, `text/white-0` | The black Sign in with Apple button, its mark and its label | 1 each | | `text/disabled-400` | The placeholder of an empty field | 1 | | Style | Uses | Screens | | --- | --- | --- | | `base/default` | 12 | 4 | | `sm/default` | 9 | 3 | | `xs/default` | 6 | 3 | | `lg/emphasized` | 5 | 4 | | `3xl/emphasized` | 4 | 4 | | `sm/emphasized` | 3 | 3 | | `base/emphasized` | 2 | 1 | | `backdropBlur/md` | 2 | 1 | | Collection | Modes | What it drives here | | --- | --- | --- | | `Color Tokens` | Light, Dark | Every bound paint above, pinned on each frame | | `Platform` | ios-md, ios-lg, android, ios-duo-outer, ios-duo-inner | Status bar and platform metrics, pinned to ios-md | | `Foundations` | Default | Spacing, radius and control sizing, plus the two primitives above | | `Typography` | Default | Headline and supporting text | | `Platform Bridge` | Brand, System | Not pinned on the frames, so the default mode applies | | `Motion` | Default | Not used on these screens | Paints are every visible solid fill and stroke on the four light frames, inside instances included, counted by bound variable name on October 3, 2026. A text layer that mixes two colors counts once for each. --- --- title: Settings description: Settings screens for iOS in Figma, light and dark: a grouped menu, an account form and a preferences list with switches, built from Appetite UI components. group: App screens source: https://www.appetiteui.com/docs/screens-settings dateModified: 2026-10-03 --- # Settings Updated: October 3, 2026. A settings menu, an account form and a preferences list with switches, drawn light and dark. 17 of the 29 instances placed on them are List rows, so one change to List reaches the whole settings area. ## Preview Three screens for the part of an app nobody demos: a menu that groups its rows, an account form, and a preferences list that carries switches. Specimen: Settings, three screens, light and dark. 393 x 852 each, Platform ios-md. | Screen | What it shows | Built from | | --- | --- | --- | | Menu | Nine rows in three groups, Profile, App and Integrations, the last one cut off at the bottom edge | Top Bar, List | | Account setup | A photo, three fields and a Change password button | Top Bar, Avatar, Text Input, Button | | Selection | The Preferences list: values, four switches and two links to help | Top Bar, List, Toggle | Each screen is drawn in Light and in Dark, with Color Tokens set on the frame itself, so the dark screens are the same instances resolved against the other mode. On Selection the Dark mode switch is off in the light screen and on in the dark one. The Menu screen is titled Settings and the Selection screen Preferences. All three screens set the title inline, beside the back button. ## What does a settings screen need from a component library? Rows that group, a switch for every yes or no choice, a top bar that goes back and confirms, and fields for the account. A settings screen needs grouped rows, a switch for each yes or no choice, a top bar with back and confirm, and form fields. In this set those are List, Toggle, Top Bar and Text Input, and List alone is 17 of the 29 instances placed on the three screens. | Need | Component | Where it appears | | --- | --- | --- | | Group rows under a heading | List | Menu, nine rows in three groups, and Selection, eight rows in three groups | | Switch a setting on or off | Toggle inside a List row | Selection: Dark mode, Push notifications, Email alerts and SMS alerts | | Go back and confirm | Top Bar with two Buttons | All three screens, a confirm button on Selection and Account setup | | Edit account details | Text Input | Name, Email and Phone on Account setup | | Show who is signed in | Avatar | Account setup | The minimum touch target on iOS is 44 pt. The frames pin Platform to ios-md, where `platform/min-touch-target` reads 44. The android mode of the same variable reads 48 dp. ## What are the Settings screens built from? 76 instances across the 3 screens. 38 are Appetite UI components, 37 are Lucide icons with 20 different names, and the last is a flag asset in the phone field. 7 components carry the whole set. 29 instances sit directly on the frames and the rest sit inside them. Placed counts an instance that is not inside another instance. Nested counts one that is, which is where the Toggles, the Top Bar buttons and every glyph live. A component is counted by its set name, and an icon is an instance named in lowercase. The dark row holds the same instances as the light row. | Component | Placed | Nested | Where | | --- | --- | --- | --- | | [List](https://www.appetiteui.com/docs/list) | 17 | 0 | Menu 9, Selection 8 | | [iOS / Status Bar](https://www.appetiteui.com/docs/ios) | 3 | 0 | All three screens | | [Top Bar](https://www.appetiteui.com/docs/top-bars) | 3 | 0 | All three screens | | [Text Input](https://www.appetiteui.com/docs/input) | 3 | 0 | Account setup | | [Button](https://www.appetiteui.com/docs/button) | 2 | 5 | Placed on Account setup, Change avatar and Change password. Nested in the Top Bar as the back button on all three screens and the confirm button on two | | [Toggle](https://www.appetiteui.com/docs/toggle) | 0 | 4 | Selection, one in each of four List rows | | [Avatar](https://www.appetiteui.com/docs/avatar) | 1 | 0 | Account setup | | [Lucide icons](https://www.appetiteui.com/docs/icons) | 0 | 37 | Seventeen leading glyphs and eleven chevrons in List rows, the Top Bar buttons, and four on Account setup | | [Country Flags](https://www.appetiteui.com/docs/assets) | 0 | 1 | Account setup, in the Phone field | List carries 17 of the 29 placed instances, and the Toggles and the row glyphs sit inside it. That is the point in one number: change List and the settings area changes, because a settings screen is a set of content decisions. The only parts drawn by hand are 13 lines named Divider, each 345 wide with its stroke bound to `border/soft-100`, 6 on Menu and 7 on Selection. Counted on October 2, 2026 with a Plugin API script over the three light frames of the Settings page in the Appetite UI Figma file. Lucide supplies 20 different icons 37 times. ## Which tokens do the Settings screens use? Every solid fill and stroke resolves through a variable except the flag in the phone field, which makes the dark row a mode switch. The three light frames hold 171 solid fills and strokes that are bound, spread over 17 different variables. The only unbound solid paints are 6 vectors of the country flag, the colors of a flag and not a token. | Token | Where it lands | Paints | | --- | --- | --- | | `border/soft-100` | The 13 Divider lines, the group outlines, the back button outline and the Change password outline | 25 | | `bg/white-0` | Every List row, the group cards and the screen | 24 | | `text/soft-500` | Group headings, input labels and the chevrons in List rows | 22 | | `text/strong-950` | Row titles, screen titles and entered text | 21 | | `state/faded/lighter-50` | The leading tile of each List row | 17 | | `state/faded/base-500` | The glyph inside each leading tile | 17 | | `fg/strong-950` | Status Bar glyphs | 15 | | `brand/base` | The confirm button, switched on Toggle tracks and the Change avatar link | 6 | | `static/static-white-0` | Toggle knobs and the check glyph in the confirm button | 6 | | `fg/sub-700` | The back button chevron and the lock glyph | 4 | | `bg/raised` | The back button fill | 3 | | `text/sub-700` | Row values such as English and USD, and the Change password label | 3 | | `bg/soft-100` | Switched off Toggle tracks | 2 | | `border/sub-200` | The Text Input underline | 2 | | `text/disabled-400` | Hints and the empty phone number in Text Input | 2 | | `fg/soft-500`, `fg/disabled-400` | Text Input glyphs | 1 each | | Style | Uses | Screens | | --- | --- | --- | | `base/emphasized` | 19 | 3 | | `xs/default` | 6 | 2 | | `sm/default` | 6 | 2 | | `base/default` | 4 | 1 | | `xl/emphasized` | 3 | 3 | | `dropShadow/xs` | 3 | 3 | | Collection | Modes | What it drives here | | --- | --- | --- | | `Color Tokens` | Light, Dark | Every bound paint above, pinned on each frame | | `Platform` | ios-md, ios-lg, android, ios-duo-outer, ios-duo-inner | Status bar and platform metrics, pinned to ios-md | | `Foundations` | Default | Row height, group spacing and radius | | `Typography` | Default | Row titles, values and group headings | | `Platform Bridge` | Brand, System | Not pinned on the frames, so the default mode applies | | `Motion` | Default | Not used on these screens | Paints are every visible solid fill and stroke on the three light frames, inside instances included, counted by bound variable name on October 2, 2026. --- --- title: Empty State description: Empty and error screens for iOS in Figma, light and dark: a failed load and a first use state, built from Appetite UI components. group: App screens source: https://www.appetiteui.com/docs/screens-empty-state dateModified: 2026-10-02 --- # Empty State Updated: October 2, 2026. A failed load and a first use state for a finance app, drawn light and dark. Each is a status badge, a headline, one line of support, a filled Button and a quiet one. Error takes its badge from a component and Add money draws its own. ## Preview Two screens for the moments a product usually leaves blank. One thing went wrong, one thing has not happened yet, and both are laid out from the same parts as every other screen in the system. Specimen: Empty State, two screens, light and dark. 393 x 852 each, Platform ios-md. | Screen | What it shows | Built from | | --- | --- | --- | | Error | A request failed and the user can retry or go back | Status Bar, _Alert Status, Button | | Add money | Nothing has happened yet and one action fixes that | Status Bar, Button, a wallet-minimal icon in a hand drawn badge | Each screen is drawn in Light and in Dark, with Color Tokens set on the frame itself. The dark screens are the same instances resolved against the other mode. ## What are the Empty State screens built from? 9 instances across the two screens. This is the smallest set of screens in the library, and it uses the same parts as every other screen. 9 instances are counted, 8 placed directly on the frames and 1 nested. Placed counts an instance that is not inside another instance. Nested counts one that is. A component is counted by its set name, and an icon is an instance named in lowercase. The dark row holds the same instances as the light row. | Component | Placed | Nested | Where | | --- | --- | --- | --- | | [Button](https://www.appetiteui.com/docs/button) | 4 | 0 | Both screens, one filled and one quiet | | [iOS / Status Bar](https://www.appetiteui.com/docs/ios) | 2 | 0 | Both screens | | [_Alert Status](https://www.appetiteui.com/docs/alert) | 1 | 0 | Error only, drawn at 80 x 80 | | [Lucide icons](https://www.appetiteui.com/docs/icons) | 1 | 1 | The x inside _Alert Status on Error, and the wallet-minimal glyph at 36 x 36 on Add money | Add money reports no nested instance at all, which shows where its badge came from. On Error the x is nested because it sits inside _Alert Status. On Add money the wallet glyph sits at the top level because the circle around it was drawn by hand. Counted on October 2, 2026 with a Plugin API script over the two light frames of the Empty State page in the Appetite UI Figma file. ## Which component should draw an empty or error state? Empty State for a whole state, _Alert Status for the badge alone. Use [Empty State](https://www.appetiteui.com/docs/alert#empty-state), a component with a Type of Info, Error or Success, a Title, a Body, an optional second action and an Icon Swap for the glyph. These two screens do not place it: Error places the _Alert Status badge and Add money draws its badge by hand. Booking Trips empty and Foodie Cart empty place Empty State, see [Booking](https://www.appetiteui.com/docs/screens-booking) and [Foodie](https://www.appetiteui.com/docs/screens-foodie). | Property | Type | Options | Default | | --- | --- | --- | --- | | `Type` | Variant | Info, Error, Success | Info | | `Title` | Text | Any text | No transactions yet | | `Body` | Text | Any text | Your activity will appear here once you make your first payment. | | `Show secondary` | Boolean | On, off | On | | `Icon Swap` | Instance swap | Any icon | The Info glyph | The badge on its own is _Alert Status. It has one axis, Type, with four options, and each option is 64 x 64 in the component. | Type | Glyph | Use it for | | --- | --- | --- | | `Error` | x | A request failed and the user can retry | | `Warning` | exclamation | Something needs attention before it fails | | `Success` | check | A task finished and the screen has nothing left to show | | `Verified` | check | An identity or account is confirmed | Pick the type from what the user is meant to feel. On Add money the badge is a frame holding two ellipses, a 70 x 70 named Stroke filled with `bg/white-0` and a 60 x 60 named BG filled with `state/information/lighter-50`, around a wallet-minimal icon. The Type axis of _Alert Status fixes the glyph per type, so it cannot show a wallet. Empty State solves that with its Icon Swap. Four rectangles named Divider, each 345 x 179 and filled with `bg/white-0`, sit at the top and bottom of both screens and center the content. They are spacers with a fill, whatever their name says. ## Which tokens do the Empty State screens use? Every solid fill and stroke on these two frames resolves through a variable, so the badge drawn by hand survives the mode switch too. The two light frames hold 34 solid fills and strokes, spread over 9 different variables, and none is unbound. The badge fill on Add money resolves through `state/information/lighter-50`, a pale blue in Light and a 16 percent blue in Dark, which is why the dark badge reads as a deep navy. | Token | Where it lands | Paints | | --- | --- | --- | | `fg/strong-950` | Status Bar glyphs | 10 | | `bg/white-0` | The screens, the four Divider rectangles, the Stroke ellipse and the _Alert Status ring | 8 | | `brand/base` | The filled Button fills, the quiet Button labels and the wallet-minimal glyph | 5 | | `static/static-white-0` | The filled Button labels and the x in _Alert Status | 3 | | `text/strong-950` | The headline | 2 | | `text/sub-700` | The line of support | 2 | | `brand/alpha-10` | The quiet Button fill | 2 | | `state/error/base-500` | The red circle of _Alert Status | 1 | | `state/information/lighter-50` | The BG ellipse behind the wallet glyph | 1 | | Style | Uses | Screens | | --- | --- | --- | | `lg/emphasized` | 4 | 2 | | `2xl/emphasized` | 2 | 2 | | `base/default` | 2 | 2 | | Collection | Modes | What it drives here | | --- | --- | --- | | `Color Tokens` | Light, Dark | Every paint above, pinned on each frame | | `Platform` | ios-md, ios-lg, android, ios-duo-outer, ios-duo-inner | Status bar and platform metrics, pinned to ios-md | | `Foundations` | Default | The 345 content width and the block spacing | | `Typography` | Default | Headline and supporting line | | `Platform Bridge` | Brand, System | Not pinned on the frames, so the default mode applies | | `Motion` | Default | Not used on these screens | Paints are every visible solid fill and stroke on the two light frames, inside instances included, counted by bound variable name on October 2, 2026. --- --- title: Finance description: Finance app screens for Figma: dashboard, history, card settings, portfolio, pay and cards, built from Appetite UI components in light and dark. group: App screens source: https://www.appetiteui.com/docs/screens-finance dateModified: 2026-10-03 --- # Finance Updated: October 3, 2026. Finance screens for an iOS banking app, light and dark: a balance dashboard, transaction history, a card and its settings, a portfolio and a pay sheet with a QR code. Every control that has a component is an instance of it, so one token change moves every screen. ## Preview Dashboard, History, Card settings, Portfolio, Pay and Cards, each in Light and Dark. Card settings keeps the Cards tab selected, and Pay is a sheet without a tab bar. Specimen: Finance, 6 screens. 393 x 852 each, Light and Dark. | Screen | What it shows | Built from | | --- | --- | --- | | Dashboard | Total balance, four quick actions and the latest transactions | Search, Avatar, Button, Quick Action Button, Section Header, Navigation | | History | Transactions by day, with a period switch and category chips | Top Bar, Tab, Chip, Navigation | | Card settings | The card and the switches and limit that control it | Top Bar, List, Toggle, Slider, Section Header | | Portfolio | Portfolio value, a price chart and the holdings behind it | Top Bar, Badge, Chip, Section Header, Navigation | | Pay | A sheet that sends money to a person or shows a QR code | Top Bar, Segmented Control, Avatar, Button | | Cards | The card, four card actions and spending by category | Top Bar, Quick Action Button, Progress Bar, List, Navigation | The Cards tab holds the card, its four actions and the month's spending. Card settings holds the switches and the limit behind them. ## Which components build the Finance screens? Navigation, Chip, Button, List and Quick Action Button carry most of the screens, and every row that shows a merchant uses Company Logo. A banking app is a tab bar, a list of rows and a handful of controls. On the light frames 158 instances sit on each row of the Finance page: 96 are Appetite UI components and 62 are Lucide icons with 33 different names. The dark row holds the same instances, so every number below is per row. | Component | Per row | Where | | --- | --- | --- | | [Navigation](https://www.appetiteui.com/docs/navigation) | 26 | Five tab bars with four labels each, and a sixth bar on Pay, hidden behind the sheet and without labels | | [Chip](https://www.appetiteui.com/docs/chip) | 10 | History and Portfolio, five each | | [Button](https://www.appetiteui.com/docs/button) | 8 | Dashboard 2, History 1, Card settings 1, Portfolio 1, Pay 3 | | [Quick Action Button](https://www.appetiteui.com/docs/button#quickaction) | 8 | Dashboard 4, Cards 4 | | [Status Bar](https://www.appetiteui.com/docs/ios) | 6 | Every screen | | [Company Logo](https://www.appetiteui.com/docs/assets#company-logo) | 6 | Dashboard, History and Portfolio, two each | | [List](https://www.appetiteui.com/docs/list) | 6 | Card settings 3, Cards 3 | | [Top Bar](https://www.appetiteui.com/docs/top-bars) | 5 | Every screen but Dashboard | | [Tab](https://www.appetiteui.com/docs/tab) | 5 | History, one set and four selectors | | [Section Header](https://www.appetiteui.com/docs/top-bars#section-header) | 4 | Dashboard, Card settings, Portfolio, Cards | | [Toggle](https://www.appetiteui.com/docs/toggle) | 3 | Card settings, one per row | | [Segmented Control](https://www.appetiteui.com/docs/segmented-control) | 3 | Pay, one control and two selectors | | [Avatar](https://www.appetiteui.com/docs/avatar) | 2 | Dashboard, Pay | | [Search](https://www.appetiteui.com/docs/search-field) | 1 | Dashboard | | [Badge](https://www.appetiteui.com/docs/badge) | 1 | Portfolio, the change over the last day | | [Slider](https://www.appetiteui.com/docs/slider) | 1 | Card settings, the spending limit | | [Progress Bar](https://www.appetiteui.com/docs/progress) | 1 | Cards, spend against the limit | The Portfolio line chart and the Pay QR code are drawn on the frame: the table holds no chart, and the QR code is a single vector. Merchant marks are Company Logo instances, so a merchant changes in one place. Counted on October 2, 2026 with a Plugin API script over the six light frames of the Finance page in the Appetite UI Figma file. Nested and hidden instances count, parts such as navigation labels are grouped with their family, and an icon is an instance named in lowercase. ## What does a money screen need to get right? Amounts that line up, a balance that keeps its weight from screen to screen, and a color that appears only where it means something. Every amount is right aligned and carries two decimals, so the decimal points stack down a column whatever the length. A debit and a credit share one text style and differ by color alone. Only the credit takes a color, so ordinary spending reads as ordinary and the error red stays free for an error. | Element | How it is set | Color | | --- | --- | --- | | Amount, debit | Right aligned, sm/emphasized, 14 Semi Bold | `text/strong-950` | | Amount, credit | Identical style, color is the only change | `state/success/base-500` | | Balance | 60 Medium (6xl/emphasized), the cents set smaller | White over the blue header | | Portfolio value | 30 Medium, the cents in a lighter tone | Primary text | | Card number | Bullets and the last four digits, 18 Semi Bold | White on the card | History groups its rows under Today, Yesterday and Earlier. ## How do the Finance screens switch between light and dark? Each frame pins Color Tokens to Light or Dark and Platform to ios-md, so the dark row is the light layout with one mode changed. Nothing is left to inherit: a frame dropped into another file arrives in the theme it was drawn in. A frame set to Dark resolves every token against the Dark mode of Color Tokens, so the dark row is the same layout with the other values. The six light frames hold 387 solid fills and strokes bound to 36 different variables, and none is unbound. Five fills are pictures: the Dashboard header, two avatars and two card faces. Five more are gradients, the tab bar fade. The rest of the frame is Appetite UI components, whose own paints are bound the same way. A few alpha paints bind a Foundations primitive directly, the white alpha 72 on the card, the gray alpha 10 behind the tab bar labels and the black alpha 24 on Dashboard. | Token | Where it lands | Paints | | --- | --- | --- | | `text/strong-950` | Top Bar titles, Quick Action Button and List labels, Section Header titles, amounts and merchant names | 54 | | `text/soft-500` | Dates, supporting lines in List rows, inactive tab labels | 39 | | `bg/white-0` | Chip fills, the tab bar and the surface behind it, List rows | 34 | | `brand/base` | Active tab label, Section Header links, Quick Action icons, switches that are on, the slider and progress fill, the Portfolio line | 31 | | `static/static-white-0` | Text and marks over the Dashboard header picture and on the card faces, the switch handle and the slider thumb | 27 | | `text/sub-700` | Chip labels, Tab options, supporting lines in category rows | 23 | | `fg/strong-950` | The Status Bar on four screens | 20 | | `bg/weak-50` | Merchant plates, the Segmented Control track, the Pay buttons | 17 | | `fg/soft-500` | Tab bar icons at rest | 17 | | `border/soft-100` | Tab bar outline, Top Bar buttons, List dividers | 15 | | `fg/sub-700` | Merchant glyphs, Top Bar and Pay button icons | 13 | | `state/feature/base-500`, `state/stable/base-500`, `state/stable/dark-950`, `state/stable/light-200` | The shapes of the merchant marks | 12, 6, 3, 3 | | `border/sub-200` | Chip outlines, the Portfolio tooltip, the slider thumb | 10 | | `brand/lighter` | Quick Action Button icon plates | 8 | | `state/faded/lighter-50`, `state/faded/base-500` | The icon plate and glyph of List and category rows | 6, 6 | | `colors/alpha/white/alpha-72` | Holder and expiry on the card | 6 | | `colors/alpha/gray/alpha-10` | The wash behind each tab bar label | 5 | | `state/success/base-500` | Credit amounts and positive changes | 5 | | `text/on-color/strong` | The Status Bar on Pay, over its dark presenting screen | 5 | | `bg/raised` | The Top Bar container and its buttons | 3 | | `bg/soft-100` | The off track of a switch, the slider track, the progress track | 3 | | `static/static-black-950` | The QR code, the Pay presenting screen, a card face | 3 | | `bg/strong-950`, `text/white-0` | The selected Chip, fill and label | 2, 2 | | `colors/alpha/black/alpha-24` | The dim behind the Search field and the card button on Dashboard | 2 | | `state/success/lighter-50`, `state/success/dark-950` | The change Badge on Portfolio | 1, 1 | | `state/error/base-500` | A negative change on Portfolio | 1 | | `text/disabled-400` | The cents of the portfolio value | 1 | | `bg/sub-200` | The grabber of the Pay sheet | 1 | | `icon/on-color` | The QR code background | 1 | | `colors/alpha/white/alpha-16` | The outline of the card face | 1 | | Style | Uses | Screens | | --- | --- | --- | | `sm/emphasized` | 35 | 6 | | `xs/default` | 32 | 5 | | `sm/default` | 27 | 6 | | `xs/emphasized` | 26 | 5 | | `base/emphasized` | 12 | 4 | | `lg/emphasized` | 8 | 4 | | `2xl/emphasized` | 6 | 5 | | `3xl/emphasized` | 3 | 2 | | `6xl/emphasized` | 2 | 2 | | `4xl/emphasized` | 1 | 1 | | `xl/emphasized` | 1 | 1 | | `dropShadow/xs` | 5 | 4 | | `dropShadow/lg` | 4 | 4 | | `dropShadow/sm` | 3 | 3 | | `backdropBlur/md` | 2 | 1 | Paints are every visible solid fill and stroke on the light frames, inside instances included, counted by bound variable name on October 3, 2026. Where a token appears as both a fill and a stroke the two counts are added. A style row counts a text layer or a node that carries the style, and the Pay amount, which mixes 6xl and 3xl, counts once for each. | Collection | Modes | What it drives here | | --- | --- | --- | | `Color Tokens` | Light, Dark | Every color, pinned on each frame | | `Platform` | ios-md, ios-lg, android, ios-duo-outer, ios-duo-inner | Status bar and platform metrics, pinned to ios-md | | `Foundations` | Default | Spacing, radius and control sizing | | `Typography` | Default | The 11 text styles above | | `Platform Bridge` | Brand, System | Not pinned on the frames, so the default mode applies | | `Motion` | Default | Not used on these screens | On iOS the minimum touch target is 44 pt. The frames pin Platform to ios-md, where `platform/min-touch-target` reads 44, so a tap target on these screens starts there. Android would read 48. --- --- title: Fitness description: Fitness app screens for Figma: dashboard, exercise library, analytics, profile, progress and a workout player, built from Appetite UI components. group: App screens source: https://www.appetiteui.com/docs/screens-fitness dateModified: 2026-10-03 --- # Fitness Updated: October 3, 2026. Fitness screens for an iOS workout app, light and dark: a daily dashboard with activity rings, an exercise library, analytics and progress charts, a profile and a workout player. Every control that has a component is an instance of it, so one token change moves every screen. ## Preview Dashboard, Library, Analytics, Profile, Progress and Exercise, each in Light and Dark. Five screens carry the tab bar, and Exercise is a full screen player without one. Specimen: Fitness, 6 screens. 393 x 852 each, Light and Dark. | Screen | What it shows | Built from | | --- | --- | --- | | Dashboard | The day: a week strip, activity rings, heart rate, sleep and the next workout | Avatar, Button, Button / Overlay (Button), Sparkline (Chart), Navigation | | Library | Programs and exercises, filtered by category | Top Bar, Chip, Card, Badge / Overlay (Badge), Section Header, Navigation | | Analytics | Training time for a period and weight against a target | Top Bar, Segmented Control, Chart / Bar - Stacked (Chart), Navigation | | Profile | Totals, achievements and account settings | Top Bar, Avatar, Quick Action Button, Section Header, List, Toggle, Navigation | | Progress | Weekly activity as a bar chart and the personal records behind it | Top Bar, Segmented Control, Badge, Section Header, Button, Navigation | | Exercise | A workout in progress with a timer, set, reps, weight and player controls | Top Bar, Button | The Dashboard is built around a week strip, three activity rings, heart rate, sleep and the next workout on a photo. Analytics leads with Training time and uses the same Week, Month and Year Segmented Control as Progress, Library leads with a featured program, and the statistics are set in neutral text. ## Which components build the Fitness screens? Navigation, Button and Segmented Control carry the structure, Card and Chip carry the Library, and five Photo / Gym slots hold photographs. A fitness app is a tab bar, a stack of cards and charts, and a few controls that change the period or the exercise. On the light frames 145 instances sit on each row of the Fitness page: 87 are Appetite UI components, 5 are photo slots and 53 are Lucide icons with 26 different names. The dark row holds the same instances, so every number below is per row. | Component | Per row | Where | | --- | --- | --- | | [Navigation](https://www.appetiteui.com/docs/navigation) | 25 | Five tab bars with four labels each, on every screen but Exercise | | [Button](https://www.appetiteui.com/docs/button) | 12 | Header actions, See all and View all links, and the player controls on Exercise | | [Segmented Control](https://www.appetiteui.com/docs/segmented-control) | 8 | Analytics and Progress, one control and three selectors each | | [Status Bar](https://www.appetiteui.com/docs/ios) | 6 | Every screen | | [Chip](https://www.appetiteui.com/docs/chip) | 5 | Library | | [Card](https://www.appetiteui.com/docs/card) | 5 | Library, one vertical and four horizontal | | [Top Bar](https://www.appetiteui.com/docs/top-bars) | 5 | Every screen but Dashboard | | [Quick Action Button](https://www.appetiteui.com/docs/button#quickaction) | 4 | Profile, the achievements | | [Section Header](https://www.appetiteui.com/docs/top-bars#section-header) | 4 | Library, Profile twice, Progress | | [List](https://www.appetiteui.com/docs/list) | 3 | Profile, the settings stack | | Chart / Bar - Stacked ([Chart](https://www.appetiteui.com/docs/chart)) | 3 | Analytics, the chart, its Trend Chip and its grid | | [Badge](https://www.appetiteui.com/docs/badge) | 2 | Library, the Featured overlay, and Progress | | [Avatar](https://www.appetiteui.com/docs/avatar) | 2 | Dashboard, Profile | | Sparkline ([Chart](https://www.appetiteui.com/docs/chart)) | 1 | Dashboard | | Button / Overlay ([Button](https://www.appetiteui.com/docs/button)) | 1 | Dashboard, the play button on the Up next card | | [Toggle](https://www.appetiteui.com/docs/toggle) | 1 | Profile, on the Notifications row | 5 Photo / Gym slot instances hold photographs, each one named so it can be found and replaced. Counted on October 2, 2026 with a Plugin API script over the six light frames of the Fitness page in the Appetite UI Figma file. Nested and hidden instances count, parts such as navigation labels are grouped with their family, and an icon is an instance named in lowercase. ## Which parts of the Fitness screens are drawn by hand? Analytics places a Chart component. The activity rings, the week strip, the Progress bars and the weight rail are drawn on the frame. Analytics places Chart / Bar - Stacked with its Trend Chip, so a chart restyle there follows the component. The table above lists one bar chart and no ring or slider, so the three activity rings and the week strip on Dashboard, the seven bars on Progress and the weight rail on Analytics are drawn on the frame. They resolve through variables like everything else, and they are where a chart or progress component would plug in. ## How do the Fitness screens switch between light and dark? Each frame pins Color Tokens to Light or Dark and Platform to ios-md, so the dark row is the light layout with one mode changed. Nothing is left to inherit: a frame dropped into another file arrives in the theme it was drawn in. A frame set to Dark resolves every token against the Dark mode of Color Tokens, so the dark row is the same layout with the other values. The six light frames hold 422 solid fills and strokes bound to 47 different variables, and none is unbound. The activity rings, the week strip and the bars resolve through the same variables, among them the three `chart/series` colors on Analytics. Nine fills are pictures: two avatars, the Up next card, the featured program, four exercise thumbnails and the Exercise photograph. Seven more are gradients: the tab bar fade on five screens and a shade over each of the Up next and Exercise photographs. | Token | Where it lands | Paints | | --- | --- | --- | | `text/soft-500` | Tab bar labels at rest, units, captions and meta lines | 54 | | `text/strong-950` | Numbers, Top Bar titles and Section Header titles | 48 | | `brand/base` | Active tab label, Section Header links, selected states | 30 | | `fg/strong-950` | The Status Bar on five screens and primary icons | 29 | | `bg/white-0` | The tab bar, Chip fills and exercise rows | 25 | | `text/sub-700` | Chip and selector labels, exercise subtitles | 24 | | `border/soft-100` | Tab bar and exercise row outlines, Top Bar buttons | 21 | | `fg/sub-700` | Chart labels and header icons | 16 | | `fg/soft-500` | Tab bar icons at rest | 15 | | `bg/raised` | Top Bar containers and cards | 14 | | `state/success/base-500` | Done days on the week strip and completed marks | 12 | | `border/sub-200` | Chart gridlines, Chip outlines, dividers between stats | 11 | | `bg/grouped-canvas` | The screen itself and the surface of the tab bar fade | 10 | | `chart/series-1`, `chart/series-2`, `chart/series-3` | The three segments of each stacked column on Analytics, and the legend dots | 8, 8, 8 | | `bg/sub-200` | Progress bar fills and the weight rail | 7 | | `static/static-white-0` | Text and marks over photographs, the switch handle | 13 | | `colors/alpha/gray/alpha-10` | The wash behind each tab bar label | 5 | | `text/disabled-400` | The weight statistics on Analytics | 5 | | `state/error/base-500` | The heart rate icon, the Sparkline and its end dot on Dashboard, and one mark on Profile | 4 | | `state/success/lighter-50`, `state/success/dark-950` | Ring track, Trend Chip, achievement plate and Badge | 4, 3 | | `state/feature/base-500`, `state/feature/light-200`, `state/feature/lighter-50` | Sleep: the moon, the Night bars, a record plate | 3, 6, 1 | | `text/on-color/strong` | The selected day on the week strip | 3 | | `fg/disabled-400` | The trend icons on Progress records | 3 | | `state/faded/lighter-50`, `state/faded/base-500` | The icon plate and glyph of the Profile settings rows | 3, 3 | | `state/warning/lighter-50`, `state/warning/base-500` | Achievement and record plates, the Stand ring | 2, 2 | | `brand/lighter` | Achievement and record plates | 2 | | `bg/scrim` | The dim under overlays on photographs | 2 | | `bg/elevated-1` | The Segmented Control track on Analytics and Progress | 2 | | `bg/strong-950`, `text/white-0` | The value chip on Progress and the selected Chip, fill and label | 2, 1 | | `static/static-white-alpha-70` | The caption and meta on the Up next card | 2 | | `brand/alpha-10` | The Exercise Button wash | 2 | | `brand/alpha-16` | The Move ring track | 1 | | `state/away/lighter-50`, `state/away/base-500` | The Stand ring track, progress and label | 1, 2 | | `bg/soft-100`, `state/highlighted/base-500` | The track and the fill of the weight ring on Analytics | 1, 1 | | `state/error/lighter-50` | An achievement plate on Profile | 1 | | `glass/border` | The outline of the Featured overlay Badge | 1 | | `static/static-black-950` | The heart on the featured card | 1 | | Style | Uses | Screens | | --- | --- | --- | | `xs/emphasized` | 47 | 5 | | `xs/default` | 27 | 5 | | `sm/default` | 26 | 5 | | `2xl/emphasized` | 17 | 5 | | `base/emphasized` | 16 | 4 | | `sm/emphasized` | 14 | 4 | | `lg/emphasized` | 9 | 5 | | `xl/emphasized` | 8 | 3 | | `3xl/emphasized` | 3 | 3 | | `4xl/emphasized` | 1 | 1 | | `6xl/emphasized` | 1 | 1 | | `dropShadow/xs` | 15 | 6 | | `dropShadow/lg` | 5 | 5 | | `backdropBlur/md` | 2 | 2 | | `backdropBlur/sm` | 2 | 1 | | `dropShadow/sm` | 1 | 1 | Paints are every visible solid fill and stroke on the light frames, inside instances included, counted by bound variable name on October 2, 2026. Where a token appears as both a fill and a stroke the two counts are added. A style row counts a text layer or a node that carries the style. | Collection | Modes | What it drives here | | --- | --- | --- | | `Color Tokens` | Light, Dark | Every color, pinned on each frame | | `Platform` | ios-md, ios-lg, android, ios-duo-outer, ios-duo-inner | Status bar and platform metrics, pinned to ios-md | | `Foundations` | Default | Spacing, radius and control sizing | | `Typography` | Default | The 11 text styles above | | `Platform Bridge` | Brand, System | Not pinned on the frames, so the default mode applies | | `Motion` | Default | Not used on these screens | On iOS the minimum touch target is 44 pt. The frames pin Platform to ios-md, where `platform/min-touch-target` reads 44, so a tap target on these screens starts there. Android would read 48. --- --- title: Social description: Social app screens for Figma: feed, explore, search, chats, profile, followers, stories and new post, built from Appetite UI components in light and dark. group: App screens source: https://www.appetiteui.com/docs/screens-social dateModified: 2026-10-03 --- # Social Updated: October 3, 2026. Social screens for an iOS app, light and dark: a feed, explore and search, a chat list and a thread, a profile and its followers, stories and a new post. Every control that has a component is an instance of it, so one token change moves every screen. ## Preview Home, Explore, Search, Chats, Chat, Profile, Followers, Story and New post, each in Light and Dark. Six screens carry the tab bar, and Chat, Story and New post are full screen. Specimen: Social, 9 screens. 393 x 852 each, Light and Dark. | Screen | What it shows | Built from | | --- | --- | --- | | Home | Stories and the feed, titled For you | Top Bar, Avatar, Button, Navigation | | Explore | A photo grid under search and topic chips | Search, Chip, Navigation | | Search | People matching a search, each with a Follow button | Search, Avatar, Button, Navigation | | Chats | Stories with online dots and the list of conversations | Top Bar, Search, Avatar, Button, Navigation | | Chat | One conversation and its reply field | Top Bar, Avatar, Button, Composer ([Input](https://www.appetiteui.com/docs/input)) | | Profile | A profile header, counts and a photo grid | Avatar, Button, Navigation | | Followers | The people who follow an account | Top Bar, Search, Avatar, Button, Navigation | | Story | One story with a progress bar and a reply field | Avatar, Button, Composer (Input) | | New post | A photo, a caption and the options for posting it | Top Bar, Button, Text Area (Input), List, Toggle | The reply field on Chat and Story is the Composer component. Chats and the Chat thread are separate frames. ## Which components build the Social screens? Avatar, Button and Navigation carry most of the screens, and Search, Chip, List, Composer and Text Area cover the rest. A social app is faces, follow buttons and a tab bar. On the light frames 218 instances sit on each row of the Social page: 148 are Appetite UI components from 11 sets and 70 are Lucide icons with 26 different names. The dark row holds the same instances, so every number below is per row. | Component | Per row | Where | | --- | --- | --- | | [Avatar](https://www.appetiteui.com/docs/avatar) | 51 | Every screen but Explore and New post, including seven presence dots on Chats | | [Button](https://www.appetiteui.com/docs/button) | 37 | Every screen but Explore, nine each on Search and Followers | | [Navigation](https://www.appetiteui.com/docs/navigation) | 30 | Six tab bars with four labels each | | [Status Bar](https://www.appetiteui.com/docs/ios) | 9 | Every screen | | [Top Bar](https://www.appetiteui.com/docs/top-bars) | 5 | Home, Chats, Chat, Followers, New post | | [Search](https://www.appetiteui.com/docs/search-field) | 4 | Explore, Search, Chats, Followers | | [Chip](https://www.appetiteui.com/docs/chip) | 4 | Explore | | [List](https://www.appetiteui.com/docs/list) | 4 | New post, the four option rows | | [Composer](https://www.appetiteui.com/docs/input#composer) | 2 | Chat and Story, the reply field | | [Text Area](https://www.appetiteui.com/docs/input#area) | 1 | New post, the caption | | [Toggle](https://www.appetiteui.com/docs/toggle) | 1 | New post, Also share to your story | Counted on October 2, 2026 with a Plugin API script over the nine light frames of the Social page in the Appetite UI Figma file. Nested and hidden instances count, parts such as navigation labels are grouped with their family, and an icon is an instance named in lowercase. ## Which parts of the Social screens are drawn by hand? Message bubbles, the Story progress segments and the photographs. Everything with a component is placed as one. The table holds no message bubble and no progress component, so the bubbles on Chat and the five progress segments on Story are drawn on the frame. The photographs on Home, Explore, Profile, Story and New post are content and belong there. ## How do the Social screens switch between light and dark? Each frame pins Color Tokens to Light or Dark and Platform to ios-md, so the dark row is the light layout with one mode changed. Nothing is left to inherit: a frame dropped into another file arrives in the theme it was drawn in. A frame set to Dark resolves every token against the Dark mode of Color Tokens, so the dark row is the same layout with the other values. The nine light frames hold 412 solid fills and strokes bound to 27 different variables, and none is unbound. Everything else is a picture or a gradient: the photographs and avatars, the story ring gradient and its bound stops, the tab bar fade and the dark scrim at the foot of Story. A few alpha paints bind a Foundations primitive directly, as on the Composer over the Story photograph, and the avatar background binds one of the yellow primitives. | Token | Where it lands | Paints | | --- | --- | --- | | `text/soft-500` | Tab bar labels at rest, search placeholders, timestamps | 56 | | `fg/strong-950` | The Status Bar on eight screens and primary icons | 48 | | `text/strong-950` | Top Bar titles, counts, names and the Home captions | 47 | | `bg/white-0` | The tab bar and the surface behind it, the ring around an avatar status | 40 | | `text/sub-700` | Button labels on user rows, bubble timestamps, Chip labels | 32 | | `brand/base` | Follow buttons, the active tab label, links | 28 | | `fg/soft-500` | Tab bar icons at rest | 27 | | `static/static-white-0` | Button labels on brand, story progress segments, text over photographs | 27 | | `border/soft-100` | Story and chat row rings, tab bar outline | 24 | | `bg/weak-50` | User row buttons, the Search bar, message bubbles | 21 | | `fg/sub-700` | Camera icons, Top Bar icons | 15 | | `state/success/base-500` | The online mark of an avatar and a caption | 7 | | `bg/raised` | Top Bar containers and buttons | 6 | | `colors/alpha/gray/alpha-10` | The wash behind each tab bar label | 6 | | `border/sub-200` | Chip outlines and the Text Area field | 5 | | `state/faded/base-500` | The icon glyphs of the New post rows | 4 | | `state/information/base-500` | The sent bubbles on Chat and the hashtags in the Home captions | 4 | | `colors/yellow/200` | Avatar backgrounds | 3 | | `bg/strong-950` | Message text on Chat | 3 | | `colors/alpha/white/alpha-24` | The Composer field and send button over the Story photograph | 2 | | `colors/alpha/black/alpha-24`, `colors/alpha/white/alpha-72` | The Composer field and its placeholder over the Story photograph | 1, 1 | | `text/on-color/strong` | An avatar glyph on Home | 1 | | `brand/alpha-10` | The wash on a post header Button | 1 | | `bg/soft-100`, `fg/disabled-400` | The send button on Chat, fill and icon | 1, 1 | | `text/disabled-400` | A timestamp on Chat | 1 | | Style | Uses | Screens | | --- | --- | --- | | `sm/default` | 42 | 8 | | `sm/emphasized` | 28 | 5 | | `base/emphasized` | 28 | 4 | | `xs/emphasized` | 27 | 6 | | `xs/default` | 22 | 5 | | `2xl/emphasized` | 4 | 4 | | `lg/emphasized` | 4 | 4 | | `base/default` | 3 | 3 | | `xl/emphasized` | 2 | 2 | | `dropShadow/xs` | 6 | 5 | | `dropShadow/lg` | 6 | 6 | | `backdropBlur/sm` | 2 | 1 | Paints are every visible solid fill and stroke on the light frames, inside instances included, counted by bound variable name on October 3, 2026. Where a token appears as both a fill and a stroke the two counts are added. A style row counts a text layer or a node that carries the style, and a text layer that mixes two colors or two styles counts once for each. | Collection | Modes | What it drives here | | --- | --- | --- | | `Color Tokens` | Light, Dark | Every color, pinned on each frame | | `Platform` | ios-md, ios-lg, android, ios-duo-outer, ios-duo-inner | Status bar and platform metrics, pinned to ios-md | | `Foundations` | Default | Spacing, radius and control sizing | | `Typography` | Default | The 9 text styles above | | `Platform Bridge` | Brand, System | Not pinned on the frames, so the default mode applies | | `Motion` | Default | Not used on these screens | On iOS the minimum touch target is 44 pt. The frames pin Platform to ios-md, where `platform/min-touch-target` reads 44, so a tap target on these screens starts there. Android would read 48. --- --- title: AI screens description: Eleven AI assistant screens for iOS in Figma, light and dark: new chat, streaming replies, sources, attachments, errors and a history drawer. group: App screens source: https://www.appetiteui.com/docs/screens-ai dateModified: 2026-10-03 --- # AI screens Updated: October 3, 2026. Eleven screens for an AI assistant in light and dark: an empty prompt, a streaming answer with cited sources, an image result, and the states a model forces you to handle. Every control is an instance of a component you already have, so one token change moves all 11 screens. ## Preview A new chat, a thread with sources, a reply that is still generating, an image result, an attachment, an error, and the history drawer with its menu. Each screen is drawn in Light and in Dark. Specimen: AI screens, 11 screens. 393 x 852 each, Light and Dark. | Screen | What it shows | Built from | | --- | --- | --- | | New chat | An empty prompt with four suggestions | AI / Prompt Composer, Chip, Button | | Tools | The composer menu: image, file, research, agent and study | Context Menu, AI / Prompt Composer, Chip | | Thread | A question, a reply with a table and sources, and the reply actions | AI / Message, AI / Prompt Composer | | Generating | A reply that is still arriving, with a stop button | AI / Message, AI / Prompt Composer | | Image | A picture reply with Save, Variations and Edit | AI / Message, Button | | Attachment | A file waiting in the composer, a numbered list in the reply | AI / Message, AI / Prompt Composer | | Error | A failed reply with a retry | AI / Message, Button | | History | The drawer with navigation and recent chats | Navigation Drawer, AI / Message | | Manage chat | A recent chat with Pin, Rename and Delete | Navigation Drawer, Context Menu | | Projects | One project with its files, instructions and chats | Top Bar, Chip, AI / Prompt Composer | | Instructions | A sheet for the rules a project follows | Action Sheet, Input, Button | Each screen is drawn in Light and in Dark, with Color Tokens set on the frame itself, and the dark screens are the same instances resolved against the other mode. AI is also drawn for the outer and inner display of iPhone Duo, see [iPhone Duo screens](https://www.appetiteui.com/docs/screens-iphone-duo). The History drawer lists Library, Projects, Agents, Explore, Scheduled and Images above Recents, with Chat and settings buttons at the foot. The composer opens the Tools menu. ## How does a chat interface handle generating, error and attachment states? The composer stays put and changes its button. The error is a banner in the thread. The file sits in the composer. While a reply generates, the composer stays where it is and its send button becomes a blue stop button. When a reply fails, the error appears in the thread as a banner with a Try again Button, and an attachment sits inside the composer above the text as a file row with a remove button. | State | Screen | What changes | Built from | | --- | --- | --- | --- | | Generating | Generating | A typing indicator under the last reply, and a stop button in place of send | AI / Message, AI / Prompt Composer | | Error | Error | A red banner with a warning glyph, the message and a Try again Button | AI / Message, Button | | Attachment | Attachment | A file row with a name, a size and a remove button, and an active send button | AI / Prompt Composer | | Image result | Image | A picture in the reply and three Buttons under it | AI / Message, Button | The minimum touch target on iOS is 44 pt. The frames pin Platform to ios-md, where `platform/min-touch-target` reads 44. The android mode of the same variable reads 48 dp. ## What are the AI screens built from? 270 instances across the 11 screens. Two components, Message and Prompt Composer, carry the assistant itself. 129 instances sit directly on the frames: 84 are components, instances of 9 component sets and one helper row, and 45 are Lucide icons with 12 different names. Another 141 sit inside those, 90 of them icons, so the screens use 39 different icon names in all. Placed counts an instance that is not inside another instance. Nested counts one that is. A component is counted by its set name, an icon is an instance named in lowercase and a helper part begins with an underscore. The dark row holds the same instances as the light row. Four of the 11 screens are another screen with something laid over it: Tools, History, Manage chat and Instructions. Each brings its own status bar, which is why those screens count two. | Component | Placed | Nested | Where | | --- | --- | --- | --- | | [Button](https://www.appetiteui.com/docs/button) | 21 | 15 | Placed on every screen except Projects and Instructions, five of them on Image. Nested in the Top Bar, the drawer, the Error banner and the Action Sheet | | [AI / Message](https://www.appetiteui.com/docs/ai-component) | 20 | 0 | Thread, Generating, Image, Attachment, Error, History, Manage chat | | [iOS / Status Bar](https://www.appetiteui.com/docs/ios) | 15 | 0 | Every screen, two on the four with an overlay | | [AI / Prompt Composer](https://www.appetiteui.com/docs/ai-component) | 10 | 0 | Every screen except Instructions | | [Chip](https://www.appetiteui.com/docs/chip) | 10 | 0 | New chat 4, Tools 4, Projects 1, Instructions 1 | | [Top Bar](https://www.appetiteui.com/docs/top-bars) | 2 | 0 | Projects, Instructions | | [Context Menu](https://www.appetiteui.com/docs/context-menu) | 2 | 0 | Tools, Manage chat | | [Navigation Drawer](https://www.appetiteui.com/docs/drawer) | 2 | 0 | History, Manage chat | | [Action Sheet](https://www.appetiteui.com/docs/action-sheet) | 1 | 0 | Instructions | | _Drawer Item | 1 | 26 | Thirteen rows in each drawer, and the lifted row on Manage chat | | _Context Menu Item | 0 | 8 | Five on Tools, three on Manage chat | | [Text Area](https://www.appetiteui.com/docs/input) | 0 | 1 | Instructions | | [Compact Button](https://www.appetiteui.com/docs/button#compact) | 0 | 1 | Instructions, the close button | | [Lucide icons](https://www.appetiteui.com/docs/icons) | 45 | 90 | Placed: 12 names in the header, thread actions, source cards and project rows. Nested: the composer, the drawer, the menus and the buttons | | Overlay | Screens | What it opens onto | | --- | --- | --- | | Context Menu | Tools, Manage chat | New chat, and the thread with the drawer already open | | Navigation Drawer | History, Manage chat | The thread, pushed aside | | Action Sheet | Instructions | The Projects screen | This set draws more by hand than the others. No List or Dropdown is placed, so the model switcher under the header, the icon tile on New chat and Projects, the Files and Instructions rows, the source cards and the table inside a reply are local layout. In all, 135 layout frames and 61 text layers sit outside any instance, and the only drawn shape is one 393 x 852 rectangle, the Scrim on Manage chat. A change to List or Dropdown does not reach these parts. Manage chat is the deepest screen in the set: a thread, a drawer over it and a menu over that. It places 17 instances and nests 37 more, so it is the one to look at when you want to know whether the layering holds. Counted on October 2, 2026 with a Plugin API script over the 11 light frames of the AI page in the Appetite UI Figma file. ## Which tokens do the AI screens use? Every solid fill and stroke on the screens resolves through a variable. Frames sit in a variable mode and read down through the same collections as every component. The 11 light frames hold 511 solid fills and strokes that are bound, spread over 22 different variables, and none is unbound. Two things are not solid paints bound to a variable: the Fade mask gradient in the drawer on History and Manage chat has three stops that are not bound, and one fill in the Error banner uses the Foundations primitive `colors/alpha/red/alpha-10` directly. | Token | Where it lands | Paints | | --- | --- | --- | | `text/strong-950` | Titles and message text, the drawer rows, the menus | 91 | | `fg/strong-950` | Status Bar glyphs and the drawer icons | 77 | | `fg/sub-700` | Icons in Buttons, the composer, the drawer, the menus and the Top Bar | 62 | | `fg/soft-500` | Chevrons, Chip icons and the thread action icons | 55 | | `border/soft-100` | The composer outline, source cards, row and top bar outlines | 42 | | `bg/white-0` | The screens, Chips, the composer and the drawer | 39 | | `bg/soft-100` | Message bubbles, composer buttons and icon tiles | 33 | | `text/sub-700` | Supporting lines, Chip labels, the Action Sheet note | 33 | | `text/soft-500` | The Ask anything placeholder and meta lines | 22 | | `border/sub-200` | The Chip outline | 10 | | `bg/raised` | Floating surfaces: Top Bar buttons, Context Menu, Action Sheet and the lifted drawer row | 8 | | `fg/disabled-400` | The send glyph while the composer is empty | 8 | | `brand/base` | The send and stop buttons, the Chat button and the Save instructions button | 7 | | `bg/weak-50` | The note in the Action Sheet and quiet Button fills | 6 | | `static/static-white-0` | Labels and glyphs on a brand fill | 5 | | `state/error/base-500`, `lighter-50`, `dark-950` | The Error banner and the Delete item | 4, 1, 1 | | `bg/scrim` | The dim behind each overlay | 3 | | `text/on-color/strong` | The send glyph on a brand fill | 2 | | `bg/sub-200` | The composer send button fill | 1 | | `colors/alpha/red/alpha-10` | The Try again button in the Error banner, a Foundations primitive bound directly | 1 | | Style | Uses | Screens | | --- | --- | --- | | `base/default` | 50 | 11 | | `lg/default` | 27 | 2 | | `sm/default` | 25 | 8 | | `sm/emphasized` | 20 | 6 | | `base/emphasized` | 9 | 9 | | `xs/default` | 8 | 5 | | `2xl/emphasized` | 7 | 6 | | `lg/emphasized` | 6 | 3 | | `xl/emphasized` | 2 | 2 | | `xs/emphasized` | 2 | 2 | | `dropShadow/sm` | 10 | 10 | | `dropShadow/lg` | 5 | 3 | | `dropShadow/xs` | 4 | 2 | | `dropShadow/2xl` | 3 | 3 | | `backdropBlur/sm` | 3 | 3 | | Collection | Modes | What it drives here | | --- | --- | --- | | `Color Tokens` | Light, Dark | Every bound paint above, pinned on each frame | | `Platform` | ios-md, ios-lg, android, ios-duo-outer, ios-duo-inner | Status bar and platform metrics, pinned to ios-md | | `Foundations` | Default | The primitive ramps every other collection points at | | `Typography` | Default | The type styles in the table above | | `Platform Bridge` | Brand, System | Not pinned on the frames, so the default mode applies | | `Motion` | Default | Not used on these screens | Paints are every visible solid fill and stroke on the 11 light frames, inside instances included, counted by bound variable name on October 2, 2026. --- --- title: Booking description: Booking app screens for Figma: a stays flow from capsule search and a price map to dates, guests, payment and trips, built from Appetite UI components. group: App screens source: https://www.appetiteui.com/docs/screens-booking dateModified: 2026-10-03 --- # Booking Updated: October 3, 2026. Eleven screens for one stays app, from a capsule search and a price map to dates, guests, payment and a trip list, in light and dark. Every control is an instance of an Appetite UI component, so one token change moves every screen. ## Preview Eleven screens follow one stay from search to a confirmed trip: Explore, Results, Filters, Listing, Dates, Guests, Review and pay and Confirmed, then Trips, Trips empty and Profile. Each screen is drawn in Light and in Dark. Specimen: Booking, 11 screens. 393 x 852 each, Light and Dark. | Screen | What it shows | Built from | | --- | --- | --- | | Explore | A capsule search, Stays and Experiences tabs and two rows of stay cards | Search, Tabs, Section Header, Vertical Card, Navigation | | Results | A map with price pins and a sheet of results | Top Bar, Chip, Vertical Card, Navigation | | Filters | Price range, place type, bedrooms and amenities | Top Bar, Range Slider, Chip, Stepper, List, Button | | Listing | One stay: photo, rating, host, map, amenities and a Reserve bar | Badge, Badge / Overlay, Button / Overlay, Rating / Score, Avatar, Button | | Dates | A range on a calendar and flexible date chips | Top Bar, Segmented Control, Date Picker, Chip, Button | | Guests | Four counters and a capacity note | Top Bar, Stepper, Button | | Review and pay | The stay, a price breakdown, the card and the cancellation terms | Top Bar, Price Row, List, Button | | Confirmed | A confirmation, a reference and the next three steps | Button, Lucide icons | | Trips | An upcoming trip as a large card and later trips as rows | Top Bar, Section Header, Vertical Card, Horizontal Card, Navigation | | Trips empty | The state of a traveler with no bookings | Top Bar, Empty State, Navigation | | Profile | The account rows and a Log out button | Top Bar, Avatar, List, Button, Navigation | ## What does a stays booking flow need from a component library? A search that sits above a feed, cards that carry a photo and a price, controls for narrowing, picking dates and counting guests, and a short path to pay. A stays app needs a search field, a card for one stay, chips to narrow the list, a calendar that selects a range, counters for guests and a row that shows a price. Here the search is Search, the card is Vertical Card, the calendar is Date Picker and the counters are Stepper, so a stays flow draws on the library as it ships. The price pins on the Results map are Chip instances, one per pin. | Need | Component | Where it appears | | --- | --- | --- | | Start a search | Search, Tabs | Explore | | Browse stays | Vertical Card, Horizontal Card, Section Header | Explore, Results, Trips | | Mark a place on a map | Chip | Results, six price pins | | Narrow the results | Chip, Range Slider, Stepper, List | Filters | | Pick a range of dates | Date Picker, Segmented Control, Chip | Dates | | Count guests | Stepper | Guests, and bedrooms on Filters | | Show a price and a total | Price Row, List | Review and pay | | Pay and confirm | Button | Listing, Review and pay, Confirmed | | Hold a trip list and its empty state | Horizontal Card, Empty State | Trips, Trips empty | | Move around the app | Navigation, Top Bar | Five screens carry the tab bar, eight a top bar | The tab bar floats over the content on its five screens, and a short fade behind it keeps scrolled content from showing next to the bar. Dates is the screen to open for the calendar: its range is the Range Start, Range Middle and Range End states of the Date Picker day cell (see [Picker](https://www.appetiteui.com/docs/picker)). On iOS the minimum touch target is 44 pt. The frames pin Platform to ios-md, where `platform/min-touch-target` reads 44, so that is the size a tap target on these screens starts from. Android would read 48. ## How do the Booking screens follow one stay? Booking is drawn as a stays app, and its screens share one trip. Explore opens on a capsule search with Stays and Experiences tabs and rows of cards, Results is a map with price pins and a sheet, and Trips leads with one large card for the next stay. The whole flow reads 12 to 17 February for 3 guests, from the Results header to the Review and pay total, so the screens agree with each other. The back and favorite buttons on the Listing photo are Button / Overlay, and the photo count is Badge / Overlay. ## What are the Booking screens built from? Every instance on the eleven light frames, counted once, by the component it comes from. The dark row holds the same instances, so each number is per row. 287 instances sit on the frames. 95 of them are placed directly as Appetite UI components from 22 component sets, and 7 are Lucide icons. Another 185 sit inside those. Placed counts an instance that is not inside another instance, nested counts one that is, and a component is counted by its set name, so every Button variant is a Button. An icon is any instance named in lowercase. | Component | Placed | Where it appears | | --- | --- | --- | | [Chip](https://www.appetiteui.com/docs/chip) | 17 | Results 10 (four filters, six price pins), Filters 3, Dates 4 | | [iOS / Status bar](https://www.appetiteui.com/docs/ios) | 11 | Every screen | | [Button](https://www.appetiteui.com/docs/button) | 9 | Listing 1, Filters 2, Dates 1, Guests 1, Review and pay 1, Confirmed 2, Profile 1 | | [Top Bar](https://www.appetiteui.com/docs/top-bars) | 8 | Every screen except Explore, Listing and Confirmed | | [Vertical Card](https://www.appetiteui.com/docs/card) | 8 | Explore 6, Results 1, Trips 1 | | [List](https://www.appetiteui.com/docs/list) | 8 | Filters 3, Review and pay 1, Profile 4 | | [Navigation](https://www.appetiteui.com/docs/navigation) | 5 | Explore, Results, Trips, Trips empty, Profile | | [Stepper](https://www.appetiteui.com/docs/input#stepper) | 5 | Guests 4, Filters 1 | | [Section Header](https://www.appetiteui.com/docs/top-bars#section-header) | 4 | Explore 2, Trips 2 | | [Price Row](https://www.appetiteui.com/docs/list#price) | 4 | Review and pay | | [Horizontal Card](https://www.appetiteui.com/docs/card) | 3 | Trips | | [Avatar](https://www.appetiteui.com/docs/avatar) | 2 | Listing, Profile | | [Button / Overlay](https://www.appetiteui.com/docs/button#overlay) | 2 | Listing, the back and favorite buttons on the photo | | [Badge](https://www.appetiteui.com/docs/badge) | 1 | Listing, Superhost | | [Badge / Overlay](https://www.appetiteui.com/docs/badge#overlay) | 1 | Listing, the photo count | | [Rating / Score](https://www.appetiteui.com/docs/rating#score) | 1 | Listing | | [Search](https://www.appetiteui.com/docs/search-field) | 1 | Explore | | [Tabs](https://www.appetiteui.com/docs/tab) | 1 | Explore | | [Segmented Control](https://www.appetiteui.com/docs/segmented-control) | 1 | Dates | | [Date Picker](https://www.appetiteui.com/docs/picker) | 1 | Dates | | [Range Slider](https://www.appetiteui.com/docs/slider) | 1 | Filters | | [Empty State](https://www.appetiteui.com/docs/alert#empty-state) | 1 | Trips empty | | [Lucide icons](https://www.appetiteui.com/docs/icons) | 7 | Listing 3 (wifi, waves, flame), Confirmed 4 (circle-check-big, clock, map-pin, shield-check) | Of the nested instances, 76 are icons inside other components, 78 are helper parts of larger components, and 31 are Buttons, Badges, Toggles and Compact Buttons inside bars, steppers, cards and rows. | Part | Nested | Inside | | --- | --- | --- | | Date Picker day cells | 35 | Date Picker on Dates, five weeks of seven | | Navigation labels | 20 | Navigation, four labels on each of five bars | | Card images | 11 | Vertical Card and Horizontal Card, one in each of the eleven cards | | Date Picker day labels | 7 | Date Picker on Dates, Monday to Sunday | | Tab and segment selectors | 4 | Tabs on Explore, two, and Segmented Control on Dates, two | | Date Picker month selector | 1 | Date Picker on Dates | | Component | Nested | Inside | | --- | --- | --- | | Button | 19 | Larger components such as Top Bar and Stepper | | Badge | 7 | Cards and rows | | Toggle | 3 | The three amenity rows of Filters | | Compact Button | 2 | Stepper | Not everything is an instance. 51 shapes are drawn by hand. Ten sit behind the tab bar on five screens, 27 are the bars of the price histogram behind the Range Slider on Filters, and the other 14 sit on Listing, Guests and Review and pay. Counted on October 2, 2026 with a Plugin API script over the eleven light frames of the Booking page in the Appetite UI Figma file. Hidden layers count. No third party asset is placed on these screens. ## Which tokens do the Booking screens use? No solid fill or stroke on these frames is a raw color. Each one resolves through a variable, which makes the dark row a mode switch. The eleven light frames hold 679 solid fills and strokes bound to 37 different variables, and none is unbound. Photographs and six gradients are the only paints that are not a solid color. Every frame sets its modes explicitly, `Color Tokens = Light` or `Dark` and `Platform = ios-md`, so a frame dropped into another file arrives in the theme it was drawn in. The dark frames bind the same variables and differ only in the Color Tokens mode they pin, so a rebrand at Color Tokens moves all eleven screens. | Token | Where it lands | Paints | | --- | --- | --- | | `text/sub-700` | Descriptions and secondary lines | 92 | | `text/strong-950` | Titles, stay names and prices | 86 | | `bg/white-0` | The screen and its cards | 77 | | `brand/base` | Primary buttons, the active tab and the selected date | 63 | | `border/soft-100` | Row hairlines and card outlines | 52 | | `fg/strong-950` | Primary icons | 51 | | `text/soft-500` | Captions and meta lines | 46 | | `static/static-white-0` | Text and icons over photographs | 38 | | `brand/alpha-10` | The band between the two ends of the selected date range | 6 | | `colors/yellow/400` | The rating star, a Foundations primitive | 8 | | Style | Uses | Screens | | --- | --- | --- | | `sm/default` | 58 | 9 | | `base/emphasized` | 53 | 9 | | `sm/emphasized` | 47 | 4 | | `xs/default` | 29 | 5 | | `xs/emphasized` | 29 | 6 | | `lg/emphasized` | 19 | 6 | | `xl/emphasized` | 7 | 7 | | `2xl/emphasized` | 6 | 4 | | `base/default` | 1 | 1 | | `dropShadow/xs` | 22 | 8 | | `dropShadow/sm` | 10 | 4 | | `dropShadow/lg` | 6 | 5 | | `dropShadow/md` | 6 | 1 | | `dropShadow/2xl` | 2 | 2 | | `backdropBlur/md` | 3 | 1 | | Collection | Modes | What it drives here | | --- | --- | --- | | `Color Tokens` | Light, Dark | Every paint above, pinned on each frame | | `Platform` | ios-md, ios-lg, android, ios-duo-outer, ios-duo-inner | Frame width, radius, inset and the 44 pt touch target, pinned to ios-md | | `Foundations` | Default | The primitive ramps every other collection points at | | `Typography` | Default | The 9 text styles above | | `Platform Bridge` | Brand, System | Not pinned on the frames, so the default mode applies | | `Motion` | Default | Not used on these screens | --- --- title: Foodie description: Food delivery app screens for Figma: home, restaurant, dish, cart, checkout, tracking and orders, built from Appetite UI components in light and dark. group: App screens source: https://www.appetiteui.com/docs/screens-foodie dateModified: 2026-10-03 --- # Foodie Updated: October 3, 2026. Eleven screens for one food delivery app, from a Home with Delivery and Pickup to a courier you can follow on a map, in light and dark. Every control is an instance of an Appetite UI component, so one token change moves every screen. ## Preview Eleven screens follow one order from the first search to a delivery on its way: Home, Category, Restaurant, Dish, Cart, Cart empty, Checkout and Tracking, then Orders, Favorites and Account. Each screen is drawn in Light and in Dark. Specimen: Foodie, 11 screens. 393 x 852 each, Light and Dark. | Screen | What it shows | Built from | | --- | --- | --- | | Home | A Delivery and Pickup switch, the address, a search field, cuisines, a promo card and nearby restaurants | Segmented Control, Search, Quick Action Button, Section Header, Vertical Card, Horizontal Card, Navigation | | Category | Restaurants for one cuisine with the delivery time on each photo | Top Bar, Chip, Vertical Card, Badge / Overlay, Navigation | | Restaurant | A storefront photo, rating, menu tabs and dish rows with an add button | Button / Overlay, Badge / Overlay, Rating / Score, Tabs, Button | | Dish | One dish with a size choice, extras and an Add to cart bar | List, [Radio](https://www.appetiteui.com/docs/radio), [Toggle](https://www.appetiteui.com/docs/toggle), Button / Overlay, Button | | Cart | Items with steppers, a price breakdown and a Go to checkout bar | Top Bar, Stepper, Price Row, List, Button | | Cart empty | The state of a cart with nothing in it | Top Bar, Empty State | | Checkout | Address, time, payment, tip and the total | Top Bar, List, Price Row, Button | | Tracking | A map, the arrival time, a delivery timeline and the courier | Top Bar, Avatar, Button, Lucide icons | | Orders | The order in progress with its steps, and past orders | Section Header, Progress Steps, Badge, Button, List, Navigation | | Favorites | Saved restaurants with rating, time and a heart | Top Bar, Rating / Score, Button | | Account | The account rows and a Log out button | Top Bar, Avatar, List, Button, Navigation | ## What does a food delivery flow need from a component library? Browsing that starts from a cuisine, a card that carries a photo and a delivery time, a menu that scrolls, a basket with quantities, and a delivery you can follow. A delivery app needs a mode switch, a search field, cards for restaurants, tabs for a menu, steppers for quantities, rows that show a price and a way to show progress. Here they are Segmented Control, Search, Vertical Card, Tabs, Stepper, Price Row and Progress Steps, so the whole order flow draws on the library as it ships. | Need | Component | Where it appears | | --- | --- | --- | | Switch between delivery and pickup | Segmented Control | Home | | Find food | Search, Quick Action Button, Chip | Home, Category | | Browse restaurants | Vertical Card, Horizontal Card, Badge / Overlay, Rating / Score | Home, Category, Restaurant, Favorites | | Read a menu | Tabs, Button | Restaurant | | Choose a size and extras | List with Radio and Toggle | Dish | | Build a basket | Stepper, Price Row, List | Cart | | Pay | Price Row, List, Button | Checkout | | Follow the delivery | Progress Steps, Avatar, Button | Orders, Tracking | | Show an empty cart | Empty State | Cart empty | | Move around the app | Navigation, Top Bar | Four screens carry the tab bar, eight a top bar | The Tracking screen draws its delivery timeline by hand in the look of Progress Steps, with a check for each finished step, a ring for the current one and a gray dot for the next. The Orders screen uses the component itself for the same four steps, so the two screens show one state, horizontal on Orders and vertical on Tracking. On iOS the minimum touch target is 44 pt. The frames pin Platform to ios-md, where `platform/min-touch-target` reads 44, so that is the size a tap target on these screens starts from. Android would read 48. ## How do the Foodie screens read as a delivery app? Foodie is drawn as a delivery app, and its photo controls are components. Home opens on Delivery and Pickup, the address, cuisines and a promo card, Category shows the delivery time on each photo, Restaurant has menu tabs and add buttons, and Orders leads with the order in progress. The delivery time on each card photo and the opening hours on Restaurant are Badge / Overlay, and the buttons on the Restaurant and Dish photos are Button / Overlay. Rating / Score carries the ratings on Restaurant and Favorites, and Orders tracks the order with Progress Steps. ## What are the Foodie screens built from? Every instance on the eleven light frames, counted once, by the component it comes from. The dark row holds the same instances, so each number is per row. 305 instances sit on the frames. 118 of them are placed directly as Appetite UI components from 22 component sets, and 5 are Lucide icons. Another 182 sit inside those. Placed counts an instance that is not inside another instance, nested counts one that is, and a component is counted by its set name, so every Button variant is a Button. An icon is any instance named in lowercase. | Component | Placed | Where it appears | | --- | --- | --- | | [Button](https://www.appetiteui.com/docs/button) | 21 | Home 2, Restaurant 5, Dish 1, Cart 1, Checkout 1, Tracking 2, Orders 2, Favorites 6, Account 1 | | [List](https://www.appetiteui.com/docs/list) | 20 | Dish 5, Cart 2, Checkout 4, Orders 4, Account 5 | | [iOS / Status bar](https://www.appetiteui.com/docs/ios) | 11 | Every screen | | [Vertical Card](https://www.appetiteui.com/docs/card) | 9 | Home 3, Category 6 | | [Top Bar](https://www.appetiteui.com/docs/top-bars) | 8 | Every screen except Home, Restaurant and Dish | | [Price Row](https://www.appetiteui.com/docs/list#price) | 7 | Cart 3, Checkout 4 | | [Rating / Score](https://www.appetiteui.com/docs/rating#score) | 7 | Restaurant 1, Favorites 6 | | [Quick Action Button](https://www.appetiteui.com/docs/button#quickaction) | 6 | Home, the cuisines | | [Button / Overlay](https://www.appetiteui.com/docs/button#overlay) | 4 | Restaurant 2, Dish 2, the buttons on the photo | | [Navigation](https://www.appetiteui.com/docs/navigation) | 4 | Home, Category, Orders, Account | | [Chip](https://www.appetiteui.com/docs/chip) | 4 | Category | | [Section Header](https://www.appetiteui.com/docs/top-bars#section-header) | 4 | Home 2, Orders 2 | | [Horizontal Card](https://www.appetiteui.com/docs/card) | 2 | Home | | [Stepper](https://www.appetiteui.com/docs/input#stepper) | 2 | Cart | | [Avatar](https://www.appetiteui.com/docs/avatar) | 2 | Tracking, Account | | [Segmented Control](https://www.appetiteui.com/docs/segmented-control) | 1 | Home | | [Search](https://www.appetiteui.com/docs/search-field) | 1 | Home | | [Tabs](https://www.appetiteui.com/docs/tab) | 1 | Restaurant | | [Badge / Overlay](https://www.appetiteui.com/docs/badge#overlay) | 1 | Restaurant, the opening hours | | [Badge](https://www.appetiteui.com/docs/badge) | 1 | Orders, On the way | | [Progress Steps](https://www.appetiteui.com/docs/progress-steps) | 1 | Orders | | [Empty State](https://www.appetiteui.com/docs/alert#empty-state) | 1 | Cart empty | | [Lucide icons](https://www.appetiteui.com/docs/icons) | 5 | Home 1 (chevron-down), Tracking 4 (bike, check three times) | Of the nested instances, 121 are icons inside other components, 33 are helper parts of larger components, and 28 are Badge / Overlay, Button, Radio and Toggle instances inside cards, rows and bars. | Part | Nested | Inside | | --- | --- | --- | | Navigation labels | 16 | Navigation, four labels on each of four bars | | Card images | 11 | Vertical Card and Horizontal Card, one in each of the eleven cards | | Tab and segment selectors | 6 | Tabs on Restaurant, four selectors, and Segmented Control on Home, two | | Component | Nested | Inside | | --- | --- | --- | | Button | 14 | Larger components such as Top Bar and Stepper | | Badge / Overlay | 9 | The delivery time on the photo of each card on Home and Category | | Toggle | 3 | The three extras rows of Dish | | Radio | 2 | The Regular and Large rows of Dish | Not everything is an instance. 31 shapes are drawn by hand: 8 sit behind the tab bar on four screens, and 12 sit on Tracking, which draws its delivery timeline itself. The other 11 are spread across Home, Restaurant, Dish, Cart, Checkout and Orders. Counted on October 2, 2026 with a Plugin API script over the eleven light frames of the Foodie page in the Appetite UI Figma file. Hidden layers count, and one instance is hidden. No third party asset is placed on these screens. ## Which tokens do the Foodie screens use? No solid fill or stroke on these frames is a raw color. Each one resolves through a variable, which makes the dark row a mode switch. The eleven light frames hold 683 solid fills and strokes bound to 31 different variables, and none is unbound. Photographs and six gradients are the only paints that are not a solid color. Every frame sets its modes explicitly, `Color Tokens = Light` or `Dark` and `Platform = ios-md`, so a frame dropped into another file arrives in the theme it was drawn in, and a rebrand at Color Tokens moves all eleven screens. | Token | Where it lands | Paints | | --- | --- | --- | | `text/strong-950` | Titles, restaurant and dish names, prices | 117 | | `text/sub-700` | Descriptions and secondary lines | 86 | | `text/soft-500` | Captions and meta lines | 39 | | `bg/white-0` | The screen and its cards | 77 | | `fg/strong-950` | Primary icons | 53 | | `border/soft-100` | Row hairlines and card outlines | 48 | | `brand/base` | Primary buttons, the active tab and the selected radio | 43 | | `static/static-white-0` | Text and icons over photographs | 58 | | `colors/yellow/400` | The rating star, a Foundations primitive | 18 | | `state/error/base-500` | The heart on Favorites | 6 | | Style | Uses | Screens | | --- | --- | --- | | `sm/default` | 86 | 10 | | `base/emphasized` | 66 | 8 | | `xs/default` | 29 | 3 | | `xs/emphasized` | 29 | 5 | | `lg/emphasized` | 17 | 7 | | `sm/emphasized` | 12 | 4 | | `xl/emphasized` | 10 | 9 | | `2xl/emphasized` | 10 | 4 | | `base/default` | 2 | 2 | | `dropShadow/xs` | 19 | 8 | | `dropShadow/sm` | 15 | 4 | | `dropShadow/lg` | 5 | 4 | | `backdropBlur/md` | 14 | 4 | | Collection | Modes | What it drives here | | --- | --- | --- | | `Color Tokens` | Light, Dark | Every paint above, pinned on each frame | | `Platform` | ios-md, ios-lg, android, ios-duo-outer, ios-duo-inner | Frame width, radius, inset and the 44 pt touch target, pinned to ios-md | | `Foundations` | Default | The primitive ramps every other collection points at | | `Typography` | Default | The 9 text styles above | | `Platform Bridge` | Brand, System | Not pinned on the frames, so the default mode applies | | `Motion` | Default | Not used on these screens | --- --- title: Tasks description: Task manager screens for Figma, built from Appetite UI components: my work, board, table, timeline, task, inbox and filters, in light and dark. group: App screens source: https://www.appetiteui.com/docs/screens-tasks dateModified: 2026-10-03 --- # Tasks Updated: October 3, 2026. Ten task manager screens in light and dark: a personal queue, one list shown as a board, a table and a timeline, and the task, project, inbox, search and filter screens around it. Every control is an instance of an Appetite UI component, so one token change moves every screen. ## Preview Ten screens for one task manager app. My work, Board, Table and Timeline show the same list of tasks four ways, Task and Project go one level deeper, and Inbox, Search, Filters and New task close the loop. Each screen is drawn in Light and in Dark. Specimen: Tasks, 10 screens. 393 x 852 each, Light and Dark. | Screen | What it shows | Built from | | --- | --- | --- | | My work | The personal queue: a week summary, a Today, Upcoming and Done switch, task rows | Avatar, Badge, Checkbox, Segmented Control, Floating Action Button, Navigation | | Board | The Product project as columns of task cards | Badge, Avatar, Button, Chip | | Table | The same tasks as rows with Due and Status, plus a status split | Table, Button, Chip | | Timeline | The same tasks as bars across a week | Avatar, Button, Chip | | Task | One task: fields, description, attachments, a comment field | Top Bars, Badge, Chip, Avatar, Checkbox, Composer | | Project | Completion, open tasks and hours logged | Top Bars, Key Value Row, Chart, Badge, Avatar group | | Inbox | Notifications grouped by day | Segmented Control, Avatar, Button | | Search | Recent searches and results grouped by type | Search, Chip, List | | Filters | A sheet of filters over the Board | Chip, Segmented Control, Toggle, Button | | New task | A title, property chips and the keyboard | Chip, Keyboard | ## What does a task manager flow need from a component library? One list that can be drawn several ways, a row that carries status, owner and date, and a short loop around it to filter, search and add. A task manager needs a view switcher, a row or card for one task, a way to tick it off, a table for the dense view, a sheet for filters and a composer for new work. In this set the row is Badge, Avatar and Button, the view switcher is a Chip, and the loop is Task, Inbox, Search, Filters and New task. All of it is the library as it ships. | Need | Component | Where it appears | | --- | --- | --- | | Name the view and switch it | Chip, Segmented Control | Board, Table and Timeline toolbars, the View row on Filters | | Show status, label and owner on one task | Badge, Avatar | Every list screen | | Tick a task off | Checkbox | My work, Task | | Read many tasks at once | Table | Table | | Chart progress and hours | Chart | Project | | Narrow the list | Chip, Segmented Control, Toggle, Button | Filters | | Find a task, project or person | Search, List | Search | | Write a task or a comment | Composer, Keyboard | Task, New task | | Move around the app | Navigation, Top Bars | Six screens carry the tab bar, Task and Project a top bar | On iOS the minimum touch target is 44 pt. The frames pin Platform to ios-md, where `platform/min-touch-target` reads 44, so that is the size a tap target on these screens starts from. Android would read 48. ## Which components carry the Board, Table and Timeline views? Board is cards of Badge, Avatar and Button. Table is the Table component with the same three inside its cells. Timeline is Avatar on bars over a grid drawn by hand. The three views share one toolbar: a Chip that names the view, then search, sort and filter Buttons and a New Button. They also share one status set, To do, In progress, In review and Done, which names the Table status split, the Timeline legend and the Status chips on Filters. Switching view changes the body of the screen and nothing above it. | View | Screen | Built from | Drawn by hand | | --- | --- | --- | --- | | Board | Board | Badge 9, Avatar 9, Button 8 (four in the toolbar, one Add task per column), Chip 1, the calendar and message-square icons 9 each | Four status dots in the column headers | | Table | Table | Table 1 with five header cells and twenty cells, Badge 4, Avatar 4 and Button 4 inside the cells, Button 4 in the toolbar, Chip 1 | Four dots in the status legend | | Timeline | Timeline | Avatar 7 on seven task bars, Button 4, Chip 1 | One Today column, seven day lines and four legend swatches | The frames hold more than the pictures show. The Board scrolls sideways, so its third and fourth column sit past the frame edge, and the Table carries five columns of which three are in view. Filters is the Board with a sheet over it: a `bg/scrim` fill dims the Board, and the sheet adds a Segmented Control, ten Chips and two Toggles. That is why Filters holds the most placed instances of any screen, 66 against 52 on Board. ## What are the Tasks screens built from? Every instance on the ten light frames, counted once, by the component it comes from. The dark row holds the same instances, so each number is per row. 236 instances sit directly on the frames: 174 are Appetite UI components from 21 component sets, and 62 are Lucide icons with 12 different names. Another 262 sit inside those. Placed counts an instance that is not inside another instance. Nested counts one that is. A component is counted by its set name, so every Button variant is a Button, and an icon is any instance named in lowercase. Hidden layers count, and so do layers past the frame edge. | Component | Placed | Nested | Where | | --- | --- | --- | --- | | [Avatar](https://www.appetiteui.com/docs/avatar) | 39 | 20 | Placed on My work 6, Board 9, Timeline 7, Task 3, Inbox 5, Filters 9. Nested in the Table cells, the Project avatar group, the Task composer, Search, New task and the Filters assignee chips | | [Badge](https://www.appetiteui.com/docs/badge) | 29 | 4 | Placed on My work 5, Board 9, Task 3, Project 3, Filters 9. Nested in the Table status cells | | [Button](https://www.appetiteui.com/docs/button) | 27 | 11 | Placed on Board 8, Table 4, Timeline 4, Inbox 1, Filters 10. Nested in the top bars, the floating button and the Table action cells | | [Chip](https://www.appetiteui.com/docs/chip) | 24 | 0 | Board, Table and Timeline 1 each, Task 2, Search 3, New task 5, Filters 11 | | [Status Bar](https://www.appetiteui.com/docs/ios) | 10 | 0 | Every screen | | [Checkbox](https://www.appetiteui.com/docs/checkbox) | 10 | 0 | My work 5, Task 5 | | [Navigation](https://www.appetiteui.com/docs/navigation) | 6 | 0 | My work, Board, Table, Timeline, Project, Inbox | | Emojis | 5 | 0 | The project mark on Board, Table, Timeline, Project and Filters | | [List](https://www.appetiteui.com/docs/list) | 5 | 0 | The five result rows on Search | | [Key Value Row](https://www.appetiteui.com/docs/table#key-value-row) | 4 | 0 | Project | | [Segmented Control](https://www.appetiteui.com/docs/segmented-control) | 3 | 0 | My work, Inbox, Filters | | [Top Bars](https://www.appetiteui.com/docs/top-bars) | 2 | 0 | Task, Project | | [Toggle](https://www.appetiteui.com/docs/toggle) | 2 | 0 | Filters | | [Floating Action Button](https://www.appetiteui.com/docs/button#fab) | 1 | 0 | My work | | [Table](https://www.appetiteui.com/docs/table) | 1 | 0 | Table | | [Composer](https://www.appetiteui.com/docs/input#composer) | 1 | 0 | Task | | [Chart](https://www.appetiteui.com/docs/chart), Chart / Bar | 1 | 0 | Project | | [Chart](https://www.appetiteui.com/docs/chart), Chart / Donut | 1 | 0 | Project | | [Avatar group](https://www.appetiteui.com/docs/avatar#group) | 1 | 0 | Project | | [Search](https://www.appetiteui.com/docs/search-field) | 1 | 0 | Search | | [Keyboard](https://www.appetiteui.com/docs/ios) | 1 | 0 | New task | | Lucide icons | 62 | 101 | Placed on Board 22, Filters 22, Table 6, Task 5, New task 5, Timeline 1, Project 1. Nested in toolbars, tab bars, chips and the Search field | Of the nested instances, 35 are Avatar, Badge and Button, 126 are helper parts of larger components, and icons make up the other 101. | Part | Nested | Inside | | --- | --- | --- | | Navigation labels | 24 | Navigation, four labels on each of six bars | | Table header cells, cells and cell contents | 45 | Table: 5 header cells, 20 cells and 20 contents of five kinds, four rows each | | Keyboard background, layouts, autocorrection, keys and space | 35 | iOS Keyboard, 31 of them keys | | Segmented control selectors | 9 | Segmented Control, three on each | | Chart columns and grid | 8 | Chart / Bar, 7 columns and 1 grid | | Avatar status marks | 5 | Avatar, on the five Inbox rows | Not everything is an instance. 41 shapes are drawn by hand, all of them rectangles and ellipses and none a vector or a line. Seventeen are status and unread dots, twelve are the Timeline grid, Today column and legend swatches, and twelve are the fade and surface pair behind the tab bar on six screens. Each is bound to a variable or, for the fade, a gradient. Counted on October 2, 2026 with a Plugin API script over the ten light frames of the Tasks page in the Appetite UI Figma file. An icon is an instance named in lowercase, a Lucide name from the shared icon page. No third party asset is placed on these screens. ## Which tokens do the Tasks screens use? No solid paint on these frames is a raw hex. Each fill and stroke resolves through a variable, which makes the dark row a mode switch. The ten light frames hold 1,195 solid fills and strokes bound to 57 different variables, and none is unbound. Photographs and the tab bar fade are the only fills that are not a solid color. The frames themselves bind the `fg/` text and icon variables, while the components placed on them bind the matching `text/` variables for their labels. | Token | Where it lands | Paints | | --- | --- | --- | | `fg/strong-950` | Screen titles, task names, primary icons | 162 | | `fg/soft-500` | Dates, counts, captions, inactive tab labels and icons, the To do dot on Board and Filters | 210 | | `fg/sub-700` | Description text and toolbar icons | 88 | | `bg/white-0` | The screen and its cards | 116 | | `bg/weak-50` | Panels such as the This week card, the metric tiles and the segmented control track | 22 | | `border/soft-100` | Row hairlines and card outlines | 132 | | `border/sub-200` | Outlines such as Chip and checkbox borders | 25 | | `brand/base` | New button, active tab, progress fill, the highlighted day | 55 | | `chart/series-1` | The peak column of Hours logged | 1 | | `chart/soft` | The six other Hours logged columns | 6 | | `state/feature/base-500`, `lighter-50`, `dark-950` | Mobile label: dot, fill and text of a Badge | 12, 11, 11 | | `state/information/base-500`, `lighter-50`, `dark-950` | Web label and the In progress status | 11, 10, 10 | | `state/away/base-500`, `lighter-50`, `dark-950` | Marketing label | 9, 8, 8 | | `state/warning/base-500` | The High priority dot, the In review dot, split segment and swatch on Table and Timeline, one donut segment | 6 | | `state/success/base-500` | Done dots, the Table split segment and Timeline swatch, one donut segment, the Inbox avatar mark | 10 | | `state/faded/base-500` | To do dots, split segment and swatch on Table and Timeline, one donut segment, the icons of the Search results | 10 | | `state/error/base-500` | The Due today dot and the Overdue label | 2 | | `bg/scrim` | The dim behind the Filters sheet | 1 | | Style | Uses | Screens | | --- | --- | --- | | `xs/default` | 105 | 8 | | `sm/default` | 89 | 10 | | `xs/emphasized` | 80 | 8 | | `sm/emphasized` | 68 | 9 | | `base/emphasized` | 38 | 4 | | `base/default` | 17 | 6 | | `2xl/emphasized` | 8 | 4 | | `3xl/emphasized` | 6 | 6 | | `xl/emphasized` | 4 | 4 | | `lg/emphasized` | 1 | 1 | | `dropShadow/xs` | 18 | 5 | | `dropShadow/lg` | 7 | 6 | | `backdropBlur/sm` | 1 | 1 | | Collection | Modes | What it drives here | | --- | --- | --- | | `Color Tokens` | Light, Dark | Every paint above, pinned on each frame | | `Platform` | ios-md, ios-lg, android, ios-duo-outer, ios-duo-inner | Status bar and platform metrics, pinned to ios-md | | `Foundations` | Default | Spacing, radius and control sizing | | `Typography` | Default | The 10 text styles above | | `Platform Bridge` | Brand, System | Not pinned on the frames, so the default mode applies | | `Motion` | Default | Not used on these screens | Paints are every visible solid fill and stroke on the ten light frames, inside instances included, counted by bound variable name on October 3, 2026. Where a token appears as both a fill and a stroke the two counts are added. A text layer that mixes two styles counts once for each. --- --- title: iPhone Duo description: iPhone Duo has an outer and an inner display. Appetite UI draws eight apps for both, with a vertical control rail, in light and dark. group: App screens source: https://www.appetiteui.com/docs/screens-iphone-duo dateModified: 2026-10-03 --- # iPhone Duo Updated: October 3, 2026. iPhone Duo has two displays, so each of the eight apps is drawn twice: once for the 466 x 678 outer display and once for the 951 x 669 inner display. A vertical control rail replaces the status bar and the bottom bars, and the same Appetite UI components and tokens draw both displays. ## Preview Eight apps, each laid out for the outer display and for the inner display, in light and dark. Each pair shares one rail, one set of components and one set of variables, so a rebrand moves both displays at once. Specimen: iPhone Duo, outer and inner display. outer 466 x 678, inner 951 x 669, device corner 48, light and dark. Apple's guidelines describe how iPhone Duo behaves: controls move to the vertical axis and the layout adapts to the display that is open. The point sizes on this page are working values from the Appetite UI Figma file, not an Apple specification. Each frame sets its modes explicitly. The dark frames add `Color Tokens = Dark` to `Platform = ios-duo-outer` or `ios-duo-inner`, so a frame dropped into another file arrives in the theme it was drawn in. Read from the iPhone Duo page of the Appetite UI Figma file on October 2, 2026. ## How is iPhone Duo different from iPhone? On iPhone Duo the status bar, toolbar and tab bar leave the horizontal axis and stack in a 96 point rail at the trailing edge, and the inner display adds a sidebar and a split view. On iPhone the status bar sits at the top and the tab bar at the bottom. | Aspect | iPhone | iPhone Duo | | --- | --- | --- | | Display | One, 393 x 852 in the other app screens | Two, outer 466 x 678 and inner 951 x 669 | | Status bar | Top edge, 402 wide, 59 high on ios-md and 62 on ios-lg | In the rail, 48 x 86, time over a status mark | | Tab bar | Bottom edge, 402 x 95, two to five labeled tabs | In the rail, 48 wide, two to four tabs, icons only | | Toolbar | Top edge, 402 x 84, two to five items | In the rail, 48 wide, a back button over one to three actions | | Bottom bar height | 49 | 0 | | Safe areas | Top 59 or 62, bottom 34, trailing 0 | Top 24, bottom 24, trailing 96 | | Sidebar | None | Outer display none, inner display 262 wide in the Platform collection | On the inner display held in portrait, Apple's guidelines keep horizontal bars. Use the standard `iOS / Tab Bar` and `iOS / Toolbar` there, and `iOS / Status Bar - Duo` in its Compact layout at the top. The inner frames on this page show the display in landscape, 951 wide, which is the pose that uses the rail. For the phone counterparts of each part, see [the iOS mirror](https://www.appetiteui.com/docs/ios). Read from the Platform collection, modes ios-md, ios-lg, ios-duo-outer and ios-duo-inner, and from the iOS Status Bar, Tab Bar and Toolbar sets, on October 2, 2026. ## How does an app change between the two displays? The outer display holds one pane beside the rail. The inner display holds two: a list or sidebar on the left and a detail pane on the right, with the same rail on the trailing edge. | App | Outer display, content 370 wide | Inner display | | --- | --- | --- | | Onboarding | Welcome: photo, headline, Get started | Photo pane 421 wide beside a Create account form 530 wide | | AI | One conversation with the composer, two toolbar buttons | Recents sidebar 316 wide beside the conversation 634 wide | | Finance | Dashboard: balance, quick actions, transactions | Holdings and watchlist 421 wide beside a position with a chart 530 wide | | Fitness | Exercise library | Library 421 wide beside the running exercise 529 wide | | Booking | List of stays | List 421 wide beside a map with price pins 529 wide | | Foodie | Home: search, cuisines, nearby restaurants | Restaurant list 421 wide beside the restaurant page 529 wide | | Social | Chats and stories | Chat list 421 wide beside the conversation 529 wide | | Tasks | Board with two columns in view, three views | One board across the display, four columns, 855 wide beside the rail | The detail pane runs under the rail, so a pane and the rail add up to more than the display. Dividers are 1 wide. Pane widths are the top level frames of the light inner frames in the Appetite UI Figma file, read on October 2, 2026. ## How is the control rail built? The rail is a 96 point strip on the trailing edge of both displays. Its groups are 48 wide and sit 24 in from the top, the bottom and the edge: the status mark and the toolbar on top, the tab bar at the bottom. | Group | Component | Width | Height | What it holds | | --- | --- | --- | --- | --- | | Top | `iOS / Status Bar - Duo`, Rail | 48 | 86 | The time over the 46 point status mark | | Top | `iOS / Toolbar - Duo` | 48 | 106, 168 or 222 | A back button in a 48 capsule, then a capsule of one to three actions at 36 with 18 between | | Bottom | `iOS / Tab Bar - Duo` | 48 | 110, 160 or 210 | A glass capsule of two to four tabs, 48 cells, 6 padding above and below, 2 between | The status mark is a 240 degree battery arc, stroke 3, with Wi-Fi inside it and four signal dots in the opening. It is drawn from the status bar's own vectors in `fg/strong-950`, so it follows light and dark. The selected tab is a 44 x 58 capsule filled with `iOS/systemFill` and its icon takes `iOS/tintColor`; the other tabs use `iOS/label`. The bars use the `liquidGlass/Regular` effect style. Touch targets: `platform/min-touch-target` is 44 in both Duo modes. Tab cells are 48 wide, and `_Duo / Glass Group` draws 44 point targets. The toolbar action buttons are 36 inside the capsule, so give each of them a 44 point hit area in code. The outer frames also carry a camera cutout above the rail, a drawing aid that is not part of the kit. Measured from the Duo sets on the Status Bar, Toolbar and Tab Bar pages of the Appetite UI Figma file on October 2, 2026. ## Which components have a Duo version? The rail has a Duo version of each of its parts, and Keyboard, List and Sheet each have one for the larger panels. The rail parts are placed on these screens. Keyboard, List and Sheet are published on their own component pages and are not placed here. | Component | Set id | Page | Variants | Outer | Inner | | --- | --- | --- | --- | --- | --- | | `iOS / Status Bar - Duo` | `15489:59` | Status Bar | Rail 48 x 86, Compact 92 x 48 | 8 | 8 | | `_Duo / Status mark` | `15020:34` | Status Bar | One, 46 x 46 | 8 | 8 | | `iOS / Toolbar - Duo` | `15036:337` | Toolbar | Actions 1, 2, 3 | 7 | 7 | | `iOS / Tab Bar - Duo` | `15036:29817` | Tab Bar | Tabs 2, 3, 4 | 6 | 6 | | `_Tab Bar Item - Duo` | `15024:597` | Tab Bar | State Default, Selected, 48 x 48 | 24 | 24 | | `_Duo / Glass Group` | `15488:101` | Toolbar | Orientation x Items, 48, 92 or 136 long | 0 | 0 | | `iOS / Keyboard - Duo` | `15500:203` | Keyboard | Inner landscape 934 x 218, Outer 450 x 258 | 0 | 0 | | `iOS / List - Duo` | `15499:7967` | List | Rows 2, 3, 4, 669 wide | 0 | 0 | | `iOS / Sheet - Duo` | `15500:39669` | Sheet | One, 652 x 802 | 0 | 0 | | Set | Property | Type | Options | Default | | --- | --- | --- | --- | --- | | `iOS / Status Bar - Duo` | Layout | Variant | Rail, Compact | Rail | | `iOS / Status Bar - Duo` | Time | Text | Any string | 9:41 | | `iOS / Toolbar - Duo` | Actions | Variant | 1, 2, 3 | 1 | | `iOS / Tab Bar - Duo` | Tabs | Variant | 2, 3, 4 | 2 | | `_Tab Bar Item - Duo` | State | Variant | Default, Selected | Default | | `_Tab Bar Item - Duo` | Icon | Instance swap | Any icon | house | | `_Duo / Glass Group` | Orientation | Variant | Horizontal, Vertical | Horizontal | | `_Duo / Glass Group` | Items | Variant | 1, 2, 3 | 1 | | `_Duo / Glass Group` | Icon 1 to Icon 3 | Instance swap | Any icon | One icon each | | `iOS / Keyboard - Duo` | Display | Variant | Inner landscape, Outer | Inner landscape | | `iOS / List - Duo` | Rows | Variant | 2, 3, 4 | 2 | `iOS / Sheet - Duo` is a single component and has no properties of its own. Toolbar and Tab Bar swap their icons on each button or tab instance, since the sets carry no icon property. Counts are instances on the eight light frames of each display, placed directly or nested inside another component, read on October 2, 2026. ## Which Platform variables change in the Duo modes? Two modes of the Platform collection, ios-duo-outer and ios-duo-inner, change five variables against ios-lg: both safe areas, the trailing safe area, the bottom bar height and, on the inner display only, the sidebar width. The other variables carry their ios-lg values. | Variable | ios-lg | ios-duo-outer | ios-duo-inner | | --- | --- | --- | --- | | `grid/safe-area/top` | 62 | 24 | 24 | | `grid/safe-area/bottom` | 34 | 24 | 24 | | `grid/safe-area/trailing` | 0 | 96 | 96 | | `platform/bar/bottom-height` | 49 | 0 | 0 | | `platform/duo/sidebar-width` | 0 | 0 | 262 | | `platform/duo/device-corner` | 48 | 48 | 48 | | `platform/duo/pane-corner` | 26 | 26 | 26 | | `platform/min-touch-target` | 44 | 44 | 44 | | Grid style | Columns | Margin | Gutter | Rows | | --- | --- | --- | --- | --- | | `ios-lg` | 4 | 16 | 16 | Top 62, bottom 34 | | `ios-duo-outer` | 4 | 16 | 16 | Top 24, bottom 24 | | `ios-duo-inner` | 6 | 16 | 16 | Top 24, bottom 24 | The last three rows of the variable table hold the same value in all four iOS modes. On Duo the status bar and the tab bar leave the horizontal axis, so the top and bottom safe areas stop being hardware clearance and become 24 point content margins. `grid/safe-area/trailing` is the rail: 96 on both Duo modes and 0 everywhere else. The frames on this page bind the top safe area 29 times, the trailing safe area 13 times and the device corner 48 times. The corner is 48 on all four corners of the inner display and on the two right corners of the outer display, and `dimensions/radius/lg`, 12, on the two left corners of the outer display. Platform holds 20 variables on five modes: ios-md, ios-lg, android, ios-duo-outer and ios-duo-inner. The trailing safe area and the three `platform/duo/*` variables serve the two Duo modes. For the whole collection see [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge) and [the iOS mirror](https://www.appetiteui.com/docs/ios). Read from the Platform collection and the 5 local grid styles of the Appetite UI Figma file on October 2, 2026. Binding counts are for the eight light frames of each display. ## What are the Apple and Material 3 counterparts? Apple's own parts are the iOS Status Bar, Tab Bar, Toolbar, Keyboard, List and Sheet, and each Duo version is a vertical or wider variant of one of them. Material 3 and Android have no iPhone Duo counterpart, and Appetite UI draws no Material 3 version of any Duo set. | Appetite UI component | iOS counterpart | Material 3 counterpart | What differs | | --- | --- | --- | --- | | `iOS / Status Bar - Duo` | `iOS / Status Bar`, 402 x 59 or 62 | `M3 / Status Bar`, 412 x 52 | Vertical, 48 x 86, time over a 46 point mark instead of a 402 wide row | | `iOS / Tab Bar - Duo` | `iOS / Tab Bar`, 402 x 95, Tabs 2 to 5 | `M3 / Navigation bar`, 412 x 80, Items 3 to 5 | Icons only, 2 to 4 tabs, 48 wide, no Minimized and no Search Role | | `iOS / Toolbar - Duo` | `iOS / Toolbar`, 402 x 84, Items 2 to 5 | None. `M3 / Top app bar` is a top bar | Vertical, a back button over one to three actions, 48 wide | | `iOS / List - Duo` | `iOS / List` | `M3 / List Item` | An inset group 669 wide with 2 to 4 rows of 68 | | `iOS / Keyboard - Duo` | `iOS / Keyboard`, 402 x 400 | `M3 / Keyboard` | Inner landscape spans the open device at 934 x 218, Outer is 450 x 258 | | `iOS / Sheet - Duo` | `iOS / Sheet` | `M3 / Bottom sheet`, `M3 / Side Sheet` | One component sized 652 x 802 for the inner panel | The nearest Material 3 idea to the inner display is an adaptive layout, a list beside a detail pane with a navigation rail at the wider window sizes. An Android foldable starts from the android mode and the `M3 / Navigation bar`, because Appetite UI draws no adaptive layout for Material 3. Counterpart sizes read from the iOS and Material 3 pages of the Appetite UI Figma file on October 2, 2026. ## Which tokens do the iPhone Duo frames use? Every color on the rail resolves through a variable, which makes the dark row a mode switch. The frames pin Color Tokens and Platform and leave Platform Bridge on Brand. | Token | Where it lands | Light | Dark | | --- | --- | --- | --- | | `fg/strong-950` | The time and the status mark | #0E0E0F | #FFFFFF | | `iOS/label` | Icons of the unselected tabs | #0E0E0F | #FFFFFF | | `iOS/tintColor` | The icon of the selected tab | #155DFC | #2B7FFF | | `iOS/systemFill` | The capsule behind the selected tab | #F4F5F5 | #242427 | | `bg/white-0` | The fill of every frame | #FFFFFF | #0E0E0F | | `dimensions/radius/full` | Capsules of the toolbar, the tab bar and the selection | 9999 | 9999 | | `dimensions/radius/lg` | The two left corners of the outer display | 12 | 12 | | `platform/duo/device-corner` | The other corners of both displays | 48 | 48 | | `dimensions/icon/stroke` | The stroke of the rail icons | 2 | 2 | In System mode `iOS/label` reads #000000 and #FFFFFF, `iOS/tintColor` reads #007AFF and #0A84FF, and `iOS/systemFill` reads #787880 at 16 and 36 percent. See [Platform Bridge](https://www.appetiteui.com/docs/platform-bridge). Values are the Brand mode of Platform Bridge, read on October 2, 2026. --- --- title: iOS description: Appetite UI mirrors Apple's iOS 27 patterns as Figma components: 20 pattern pages from the status bar to the Dynamic Island, in brand or system values. group: Platforms source: https://www.appetiteui.com/docs/ios dateModified: 2026-10-03 --- # iOS Updated: October 3, 2026. Apple's iOS 27 patterns, rebuilt as Figma components that read the same tokens as the rest of the system. A screen carries your brand or returns to the untouched platform values without being redrawn. ![Dark iOS components tilted around the App Store icon: a keyboard, a context menu, capsule buttons, toggles, sliders, a settings list and an AM and PM time picker.](https://www.appetiteui.com/images/au_ios_platform.webp) Appetite UI redraws the Apple patterns on your tokens and puts your brand inside them. The structure stays Apple: the same anatomy, the same spacing, the same behavior a user already knows. Color, type, radius and elevation come from your system, so a Toolbar or a Sheet reads as native and as yours at the same time. ## How does Appetite UI support iOS 26 and 27? The Apple pages follow the iOS 27 patterns: 20 pattern pages, 67 variant sets and 419 variants. Liquid Glass, which arrived in iOS 26, comes at the three transparency levels of iOS 27, and iPhone Duo has its own chrome. The Apple pages follow iOS 27 in the switch and slider, the tab bar, the status bar and the action sheet. They also carry Liquid Glass at Clear, Regular and Tinted, the Dynamic Island with its system and expanded sets, the system dialogs Passkey, Permission Alert and Review Prompt, and the iPhone Duo chrome. | Component | What it is | Measured | | --- | --- | --- | | Toggle | A wider track with a capsule knob. While pressed, the knob turns into a glass lens. | Track 64 × 28, knob 38 × 24, pressed lens 58 × 38 | | Slider | A thin track with a capsule knob and optional tick marks, at 0, 25, 50, 75 and 100 percent. | Track 6 high, knob 38 × 24, 320 wide | | Tab Bar | A floating glass capsule. The selected tab sits on a capsule fill. Search Role and Minimized variants. | Bar 62 high at padding 4, tab 54 high, component 402 × 95 | | Status Bar | Two sizes, one per device class, plus a vertical Duo version. | 402 × 62 on ios-lg, 402 × 59 on ios-md | | Action Sheet | A glass card with a left aligned title and message over full width capsule actions. A destructive action comes first, in systemRed. | Card 300 × 362 at radius 32, action row 272 × 48 | ![The iOS 27 Toggle in its eight states, idle and pressed, on and off, enabled and disabled, next to the Action Sheet: a title, a short message and four full width capsule actions, the first in red.](https://www.appetiteui.com/images/docs/ios-27-controls.webp) Toggle, eight variants, and the Action Sheet. The selected tab label reads iOS/tintColor and the others iOS/label, the selection capsule reads iOS/systemFill, and the label is 12 in Brand mode and 10 in System mode (iOS/sys/typography/tabBarLabel). Measured in the Figma file on October 2, 2026: iOS / Toggle, iOS / Slider, iOS / Tab Bar, iOS / Status Bar and iOS / Action Sheet. ## How do Brand and System mode differ? Brand mode resolves the Apple roles to Appetite UI tokens, and System mode resolves the same roles back to Apple's own values. Platform Bridge holds 53 iOS roles and each one resolves twice. Nothing in the Apple mirror is filled with a hex. Set the mode on a frame and the whole screen re-resolves: geometry and structure hold, only the values move. One swap on one collection means there is no second set of screens to keep in sync. Figure: the Platform Bridge chain, step 2. iOS / Segmented Control, Size Large, is 370 × 50 with padding 2, gap 4 and segments 46 high, in both modes. Its track reads iOS/tertiarySystemFill: flat gray in Brand, translucent in System. ## Which Apple patterns are covered? 20 pattern pages in the Apple mirror, one row each, with 67 variant sets and 419 variants in total, counted in the Figma file. | Pattern page | Sets | Variants | | --- | --- | --- | | Action Sheet | 1 | 2 | | Activity View | 2 | 14 | | Alert | 6 | 28 | | Button | 7 | 118 | | Controls | 6 | 33 | | Dynamic Island | 4 | 42 | | Face ID | 1 | 2 | | Keyboard | 13 | 55 | | List | 3 | 28 | | Live Activity | 1 | 6 | | Menu | 3 | 16 | | Notification | 1 | 3 | | Page Control | 2 | 5 | | Picker | 3 | 9 | | Sheet | 2 | 4 | | Status Bar | 2 | 4 | | Tab Bar | 5 | 25 | | Text Field | 1 | 4 | | Toggle | 1 | 8 | | Toolbar | 3 | 13 | | Total | 67 | 419 | Button and Keyboard carry the largest matrices because both cross size with state. Counted in the Figma file on October 2, 2026. A set is every component set on the page, helper sets included, and a variant is a component inside one of those sets. Loose single components are not counted. ## What are Passkey, Permission Alert and Review Prompt? They are the three system dialogs most apps show in their first minutes: saving a passkey, asking for a permission and asking for an App Store rating. Each is a component set on the Alert page, with copy you edit and the button verbs Apple uses. The three sets share the Alert card: Regular Liquid Glass at radius 32 (dimensions/radius/3xl), text on iOS/label, a primary action on iOS/tintColor and secondary actions on flat iOS/systemFill capsules. | Component | Property | Type | Options | Default | | --- | --- | --- | --- | --- | | Passkey | `Flow` | Variant | Create \| Sign In \| Cross-Device \| Security Key | Create | | Passkey | `State` | Variant | Prompt \| Verifying \| Success | Prompt | | Permission Alert | `Kind` | Variant | Photos \| Tracking \| Camera \| Microphone \| Contacts \| Location | Camera | | Review Prompt | `State` | Variant | Default \| Input Rating \| Rating Submitted | Default | | Review Prompt | `Title` | Text | Any text | Enjoying Appetite? | | Review Prompt | `Description` | Text | Any text | Tap a star to rate it on the App Store. | The three sets hold 12 Passkey variants, 6 Permission Alert variants and 3 Review Prompt variants. Title and body of Passkey and Permission Alert are editable text layers on each variant. ![Twelve Passkey dialogs in four rows. Rows are Create, Sign In, Cross-Device and Security Key. Columns are Prompt, Verifying with a Face ID glyph, and Success with a check mark. Prompts show a blue Continue button over a gray secondary one.](https://www.appetiteui.com/images/docs/ios-passkey.webp) Passkey, Flow by State, 300 wide. | Flow | Prompt actions | Success title | | --- | --- | --- | | Create | Continue, Other Options | Passkey Saved | | Sign In | Continue, Other Options | Signed In | | Cross-Device | Continue, Cancel | Signed In | | Security Key | Continue, Cancel | Signed In | Verifying waits on Face ID and offers Cancel only. Success offers Done. Heights run from 238 to 384 with the copy. ![Six permission dialogs in two rows: Camera, Microphone and Contacts with Don't Allow and OK side by side; Photos with three stacked buttons; Tracking with two gray stacked buttons; Location with three stacked buttons.](https://www.appetiteui.com/images/docs/ios-permission-alert.webp) Permission Alert, one variant per Kind. | Kind | Actions | Layout | | --- | --- | --- | | Camera | Don't Allow, OK | Side by side | | Microphone | Don't Allow, OK | Side by side | | Contacts | Don't Allow, OK | Side by side | | Photos | Select Photos, Allow Access to All Photos, Don't Allow | Stacked | | Tracking | Ask App Not to Track, Allow | Stacked | | Location | Allow While Using App, Allow Once, Don't Allow | Stacked | Two short actions sit side by side. Three actions, or a label that does not fit beside another, force the stacked layout, the same rule iOS follows. Tracking has no primary action on purpose: Apple styles both tracking choices alike so the dialog does not steer the answer. ![The Review Prompt in three cards: a title and a line of text over five empty stars captioned Tap to rate and a Not Now button; the same card with five filled yellow stars captioned Excellent and a Submit button; and a shorter card with the title, the text and a Done button.](https://www.appetiteui.com/images/docs/ios-review-prompt.webp) Review Prompt, three states. Review Prompt reuses the Rating component for the stars, with a caption under them. Default and Input Rating are 300 × 288, and Rating Submitted drops the stars and shrinks to 300 × 194. ## What is the Dynamic Island component? The Dynamic Island is the pill at the top of iPhone that grows into live information. Appetite UI draws it as three sets on one black pill: the four presentations of one activity, 23 system presentations and 10 expanded layouts. ![The four Dynamic Island presentations on a white ground: an empty black Idle pill, a Minimal pill with a small app logo beside a detached round pill, a Compact pill with a logo and the time 2:14, and a wide Expanded card with a track title, artist, progress bar and times.](https://www.appetiteui.com/images/docs/ios-dynamic-island-states.webp) Idle, Minimal, Compact and Expanded. | State | Size | Radius | What it shows | | --- | --- | --- | --- | | Idle | 125 × 37 | 18.5 | The sensor cutout at rest | | Minimal | 170 × 37 | 18.5 | An attached pill with a detached 37 capsule | | Compact | 201 × 37 | 18.5 | A leading icon and a trailing label around the cutout | | Expanded | 371 × 130 | 44 | Title, subtitle, trailing value, progress and times | Expanded is 371 wide on the 393 pt device class and 408 wide on the 430 pt class, and Apple allows 84 to 160 tall. The radius of 44 is the value Apple publishes. | Property | Type | Options | Default | | --- | --- | --- | --- | | `State` | Variant | Idle \| Minimal \| Compact \| Expanded | Idle | | `Icon` | Instance swap | Any component | Company Logo, Tidal | | `Detached Icon` | Instance swap | Any component | Company Logo, Sundial | | `Compact Label` | Text | Any text | 2:14 | | `Title` | Text | Any text | Weightless | | `Subtitle` | Text | Any text | Arlo Vance | | `Trailing Value` | Text | Any text | Now playing | | `Elapsed` | Text | Any text | 1:12 | | `Remaining` | Text | Any text | -2:48 | The apps behind the island are Company Logo placeholders, from the twelve placeholder companies in [Assets](https://www.appetiteui.com/docs/assets): Tidal, Sundial, Relay, Northwind, Pinpoint and Orbital appear across the sets. Replace the Icon swap with your own mark. ![The system presentations of the Dynamic Island as black pills with an icon and a label each, such as Silent, 84 percent charging, a red recording dot with 0:14, AirDrop, AirPods Pro, Focus, Low Battery, Airplane Mode, Hotspot, Mirroring, Voice Memo, Find My, Ring, a call, FaceTime, Timer, Turn right, Weightless, Living Room, SharePlay, Locked and SOS. Face ID is a larger square panel.](https://www.appetiteui.com/images/docs/ios-dynamic-island-system.webp) Dynamic Island - System, one variant per Type. | Type | Label width | Type | Label width | | --- | --- | --- | --- | | Face ID | 125 × 98 panel at radius 32 | Find My | 94 | | Silent | 81 | Ring | 74 | | Charging | 74 | Call | 116 | | Recording | 73 | FaceTime | 104 | | AirDrop | 91 | Timer | 82 | | Connected | 117 | Navigation | 105 | | Focus | 83 | Now Playing | 113 | | Low Battery | 120 | AirPlay | 119 | | Airplane | 133 | SharePlay | 106 | | Hotspot | 95 | Lock | 90 | | Mirroring | 102 | SOS | 73 | | Voice Memo | 120 | | | System presentations are what the island shows without an app running a Live Activity. Every pill follows one rule: the icon sits 14 from the leading edge, the label ends 15 from the trailing edge and the sensor cutout fills the middle, so a pill is 142 plus the label width. ![Ten expanded Dynamic Island layouts as black rounded cards: Media with progress, Timer, Delivery, a Call with two round buttons, Navigation with a turn arrow, a Score, an Alert with an Open Settings button, a Workout with three figures, a Recording with a waveform and a Flight with a route track.](https://www.appetiteui.com/images/docs/ios-dynamic-island-expanded.webp) Dynamic Island - Expanded, one variant per Layout. | Layout | Height | | --- | --- | | Media | 130 | | Timer | 130 | | Delivery | 130 | | Call | 138 | | Navigation | 122 | | Score | 102 | | Alert | 134 | | Workout | 132 | | Recording | 148 | | Flight | 144 | | Set | Property | Type | Options | Default | | --- | --- | --- | --- | --- | | Dynamic Island - System | `Type` | Variant | 23 types, listed above | Face ID | | Dynamic Island - Expanded | `Layout` | Variant | 10 layouts, listed above | Media | | Dynamic Island - Expanded | `Action` | Text | Any text | Open Settings | | Dynamic Island - Expanded | `Icon`, `Detached Icon`, `Compact Label`, `Title`, `Subtitle`, `Trailing Value`, `Elapsed`, `Remaining` | As in the main set | As in the main set | As in the main set | | _DI Progress | `Value` | Variant | 0 \| 25 \| 50 \| 75 \| 100 | 0 | | Live Activity | `Trailing` | Variant | Value \| Thumbnail | Value | | Live Activity | `Footer` | Variant | None \| Progress \| Actions | None | | Live Activity | `App`, `Caption`, `Title`, `Subtitle`, `Value` | Text | Any text | Appetite Delivery, now, Arriving in 12 min, Idris is 3 stops away, 12:24 | | Live Activity | `App Glyph` | Instance swap | Any component | package icon | Media, Timer and Delivery share one header, progress and meta scaffold, and only Alert uses the Action text. The progress track is the helper set _DI Progress, 331 × 6 at radius 3. The Lock Screen side of the same activity is iOS / Live Activity, 361 wide and up to 154 high with its footer. The main set carries a morph prototype: pressing an island changes it to the next presentation, Idle to Compact to Expanded and back to Idle. The transition is Smart Animate over 320 ms, the motion/duration/slow variable, on motion/easing/emphasized, cubic-bezier(0.05, 0.7, 0.1, 1). Read from the Figma reactions on October 2, 2026. ## How does the iPhone Duo chrome work? iPhone Duo moves the status bar, toolbar and tab bar off the horizontal edges onto a 96 pt control rail beside the content. Appetite UI draws the rail as Duo versions of Status Bar, Toolbar, Tab Bar, List, Keyboard and Sheet, and two Platform modes, ios-duo-outer and ios-duo-inner, set the geometry. The screens that use them are on the [iPhone Duo screens page](https://www.appetiteui.com/docs/screens-iphone-duo), 8 apps on an outer and an inner display. ![The Duo rail components: the status mark in its Rail and Compact layouts, the vertical toolbar with one, two and three glass actions, and the vertical tab bar with two, three and four icon tabs, the first tab selected in blue.](https://www.appetiteui.com/images/docs/ios-duo-chrome.webp) Status Bar - Duo, Toolbar - Duo and Tab Bar - Duo. | Component | Property | Variants | Size | | --- | --- | --- | --- | | Status Bar - Duo | Layout | Rail, Compact | 48 × 86, 92 × 48 | | Toolbar - Duo | Actions | 1, 2, 3 | 48 × 106, 168, 222 | | Tab Bar - Duo | Tabs | 2, 3, 4 | 48 × 110, 160, 210 | | Glass Group | Orientation, Items | Horizontal or Vertical, 1 to 3 | 48 × 48, 92, 136 along the axis | | List - Duo | Rows | 2, 3, 4 | 669 × 136, 204, 272 | | Keyboard - Duo | Display | Inner landscape, Outer | 934 × 218, 450 × 258 | | Sheet - Duo | None | Single component | 652 × 802 | The toolbar carries the navigation pill on top and one to three actions below, and items overflow from the bottom up. The tab bar is icon only, with 48 wide cells, and each tab has a Default and a Selected state. The toolbar actions are 36 inside their capsule. Glass Group is the shared glass surface for both, one to three targets. The Platform collection does the layout work. Duo status bar and tab bar leave the horizontal axis, so the top and bottom safe areas shrink to 24 and the bottom bar height becomes 0. The trailing safe area is 96 for the rail, and the inner display adds a 262 wide sidebar. All values are in the Platform table under [Tokens and metrics](#tokens). ## How is Liquid Glass built? Liquid Glass is an effect style on a background layer, never on a frame that holds content. The iOS components use three styles, liquidGlass/Regular, liquidGlass/Tinted and liquidGlass/Clear, the stops of the iOS 27 transparency slider. The three styles follow the iOS 27 recipe. The general effect styles, shadows and blurs are on the [Effects page](https://www.appetiteui.com/docs/effects). ![Three tiles over a wallpaper, each with a round glass control beside a solid blue primary circle. From left to right the glass is Clear, almost transparent over the brown wallpaper, Regular, frosted and light, and Tinted, a nearly opaque pale disc.](https://www.appetiteui.com/images/docs/ios-liquid-glass-styles.webp) _Glass - Control: Clear, Regular and Tinted, each beside its Primary state. | Style | Refraction | Dispersion | Frost | Light intensity | | --- | --- | --- | --- | --- | | `liquidGlass/Regular` | 0.7 | 0.2 | 6 | 0.25 | | `liquidGlass/Tinted` | 0.6 | 0.15 | 12 | 0.25 | | `liquidGlass/Clear` | 0.8 | 0.25 | 2 | 0.35 | Regular is the default stop, for bars, buttons, menus and sheets. Tinted is the fully tinted end, for busy backgrounds and Reduce Transparency. Clear lets content show through and keeps only refraction and rim light. All three share depth 30, splay 0.2 and light angle 0, plus a soft drop shadow, a one pixel edge shade and a white rim light. They differ in the inner tint: white at 32 percent for Regular, a near white at 86 percent for Tinted and white at 6 percent for Clear. The shared surface is _Glass - Control, a private set with Style Regular, Clear or Tinted and State Default or Primary. Primary drops the glass and uses a solid fill, the way iOS draws a prominent glass button. The glass buttons are iOS / Button - Liquid Glass - Text, with Style Glass or Glass Prominent and Size Small, Medium or Large, and iOS / Button - Liquid Glass - Symbol at 50 × 50. ## Tokens and metrics Device geometry lives in its own collection, one mode per device class, and the minimum touch target is 44 on every iOS mode and 48 on android. The iOS half of Platform Bridge is 53 roles. | Variable | ios-md | ios-lg | ios-duo-outer | ios-duo-inner | | --- | --- | --- | --- | --- | | `grid/safe-area/top` | 59 | 62 | 24 | 24 | | `grid/safe-area/bottom` | 34 | 34 | 24 | 24 | | `grid/safe-area/trailing` | 0 | 0 | 96 | 96 | | `grid/columns` | 4 | 4 | 4 | 6 | | `platform/min-touch-target` | 44 | 44 | 44 | 44 | | `platform/bar/top-height` | 44 | 44 | 44 | 44 | | `platform/bar/bottom-height` | 49 | 49 | 0 | 0 | | `platform/list-row/min-height` | 44 | 44 | 44 | 44 | | `platform/control/corner` | 8 | 8 | 8 | 8 | | `platform/card/corner` | 12 | 12 | 12 | 12 | | `platform/sheet/corner` | 12 | 12 | 12 | 12 | | `platform/dialog/corner` | 12 | 12 | 12 | 12 | | `platform/switch/track-width` | 64 | 64 | 64 | 64 | | `platform/switch/track-height` | 28 | 28 | 28 | 28 | | `platform/screen-padding` | 16 | 16 | 16 | 16 | | `platform/duo/sidebar-width` | 0 | 0 | 0 | 262 | | `platform/duo/device-corner` | 48 | 48 | 48 | 48 | | `platform/duo/pane-corner` | 26 | 26 | 26 | 26 | `grid/columns` is 4 on every mode except ios-duo-inner, which has 6, the same counts as the grid styles on the [Dimensions page](https://www.appetiteui.com/docs/dimensions#grids). The switch track is 64 by 28 on every iOS mode, the size of the iOS / Toggle set. ios-md and ios-lg differ in one variable, `grid/safe-area/top`, 59 on ios-md and 62 on ios-lg. The android mode sits in the same collection and is listed on the [Material 3 page](https://www.appetiteui.com/docs/material-3). Apple publishes the 44 pt target and the 11 pt minimum text, and every other number is an Appetite UI decision. Both font variables read Inter. Collection of 20 variables on five modes, read on October 2, 2026. | Role | Brand | System | | --- | --- | --- | | `iOS/tintColor` | #155DFC | #007AFF | | `iOS/label` | #0E0E0F | #000000 | | `iOS/secondaryLabel` | #48484A | #3C3C43 at 60% | | `iOS/separator` | #E9E9EA | #3C3C43 at 18% | | `iOS/systemGreen` | #22C55E | #34C759 | | `iOS/systemFill` | #F4F5F5 | #787880 at 16% | | `iOS/glassThick` | #FFFFFF at 92% | #FFFFFF at 75% | | Role | Brand | System | | --- | --- | --- | | `iOS/tintColor` | #2B7FFF | #0A84FF | | `iOS/label` | #FFFFFF | #FFFFFF | | `iOS/secondaryLabel` | #C7C7CC | #EBEBF5 at 60% | | `iOS/separator` | #2F2F31 | #545458 at 65% | | `iOS/systemGreen` | #16A34A | #30D158 | | `iOS/systemFill` | #242427 | #787880 at 36% | | `iOS/glassThick` | #242426 at 88% | #1A1A1A at 92% | | Shape and type | Brand | System | | --- | --- | --- | | `iOS/sys/shape/corner-small` | 8 | 10 | | `iOS/sys/shape/corner-large` | 24 | 26 | | `iOS/sys/shape/corner-glass` | 32 | 34 | | `iOS/sys/typography/body` | 18 | 17 | | `iOS/sys/typography/subheadline` | 14 | 15 | | `iOS/sys/typography/footnote` | 12 | 13 | | `iOS/sys/typography/tabBarLabel` | 12 | 10 | A sample of the 53 roles, resolved in Light and Dark, read in the Figma file on October 2, 2026. iOS, SwiftUI, SF Pro and SF Symbols are trademarks of Apple Inc, Material Design of Google LLC. Appetite UI is not affiliated with, endorsed by or sponsored by either; platform names describe compatibility. No Apple artwork, symbol or typeface is included. Every layer is Appetite UI's own geometry on its own tokens, in Inter with Lucide icons. --- --- title: Material 3 description: Appetite UI mirrors Material 3 as Figma components: 17 pattern pages from the app bar to the snackbar, in brand or untouched system values. group: Platforms source: https://www.appetiteui.com/docs/material-3 dateModified: 2026-10-03 --- # Material 3 Updated: October 3, 2026. Material's own patterns, rebuilt as Figma components. Every layer reads a token, so one screen carries your brand or drops back to the untouched system values without a single detach. ![Material 3 screens tilted on a lilac ground around the Google Play icon: a dark audio player, a light messaging thread, a red photo home screen with purple widgets and two clock faces in a light time picker.](https://www.appetiteui.com/images/au_m3_platform.webp) Appetite UI redraws the Material 3 patterns on your tokens and puts your brand inside them. The structure stays Material: the same anatomy, the same spacing, the same behavior a user already knows. Color, type, shape and elevation come from your system, so an App Bar or a Dialog reads as Material and as yours at the same time. ## How does Appetite UI support Material 3? The Material pages rebuild Material 3 as Figma components: 17 pattern pages, 44 variant sets and 460 variants, each with Material's own anatomy and a brand or system reading. The android mode of the Platform collection sets the touch target to 48 and list rows to 56. Hover is part of Material, so the Material sets carry a Hovered state that the Appetite UI components do not have. Measured in the Figma file on October 2, 2026. ## How do Brand and System mode differ? Brand mode resolves the Material color, shape and type roles to Appetite UI tokens, and System mode resolves the same roles back to Material's baseline. Platform Bridge is one collection with two modes, and every Material color role in it is an alias, never a literal. Switching the mode on a frame moves the whole mirror at once. Nothing is repainted and nothing is detached. Figure: the Platform Bridge chain, step 3. Geometry owned by the platform holds either way: the android switch track is 52 by 32, list rows are 56 and the touch target is 48. ## Which Material 3 patterns are covered? 17 pattern pages in the Material mirror, one row each, with 44 variant sets and 460 variants in total, counted in the Figma file. | Pattern page | Sets | Variants | | --- | --- | --- | | App Bar | 1 | 4 | | Button | 8 | 270 | | Card | 1 | 3 | | Checkbox | 1 | 6 | | Chip | 1 | 8 | | Dialog | 6 | 17 | | Keyboard | 1 | 8 | | List | 1 | 6 | | Navigation Bar | 2 | 5 | | Picker | 12 | 91 | | Radio Button | 1 | 4 | | Sheet | 4 | 10 | | Snackbar | 2 | 14 | | Status Bar | 0 | 0 | | Switch | 1 | 4 | | Text Field | 1 | 8 | | Tooltip | 1 | 2 | | Total | 44 | 460 | Button and Picker hold most of the total because both cross size or format with state. Counted in the Figma file on October 2, 2026. A set is every component set on the page, helper sets included, and a variant is a component inside one of those sets. Loose single components, Status Bar and Rich Tooltip among them, are not counted. ## How are the Switch, Snackbar, time pickers and status bar built? The time pickers read Appetite UI surfaces in Brand mode, the Snackbar comes in three configurations with an optional close affordance, and the status bar draws no camera cutout. The Switch sits beside them for its numbers. The time pickers take their colors from the Brand mode bridge: surface-container-high reads bg/weak-50, surface-container-highest reads bg/soft-100, and the tertiary family reads the brand tokens. | Component | Property | Options | | --- | --- | --- | | Switch | `Selected` | True \| False | | Switch | `Is Enabled` | True \| False | | Snackbar | `Configuration` | Text only \| Text & action \| Text & longer action | | Snackbar | `Option` | One line \| Two lines | | Snackbar | `Show close affordance` | True \| False | | Snackbar | `Supporting Text` | Any text | | Dial picker | `Format` | 12 hour \| 24 hour | | Dial picker | `Orientation` | Vertical \| Horizontal | | Keyboard picker | `Format` | 12 hour \| 24 hour | The Switch is 52 × 32 at full radius. The selected thumb is 24 with a 16 check icon, the unselected thumb is 16, and the track reads M3/sys/color/primary when selected. A state layer sits over the track at opacity 0 until a state needs it. The Snackbar is 344 wide and 48, 68 or 112 high, at radius 4 on M3/sys/color/inverse-surface. The close affordance is a 48 target around a 40 container. The time pickers are cards at radius 24 on M3/sys/color/surface-container-high, which Brand mode maps to bg/weak-50, #F4F5F5 in Light. Dial picker is 328 × 520 vertical or 572 × 384 horizontal, and Keyboard picker is 328 × 243 at 12 hour or 264 × 243 at 24 hour. The AM and PM selector is 52 × 80 in two 52 × 40 halves. The selected half reads M3/sys/color/tertiary-container with its label on M3/sys/color/tertiary, brand/lighter and brand/base in Brand mode, and the selector has Enabled, Hovered and Focused states. The status bar is 412 × 52. It draws no camera cutout, because every Android maker places the camera hole differently and the system reports it through display cutout insets. The space stays as an empty spacer, so the time and icons keep their places and no baked in black spot covers app content. ## How does Material 3 differ from iOS? Material uses 48 dp touch targets against 44 pt on iOS, rounds controls fully, and carries a Hovered state on Button and Picker. The pairs below are the closest components on each side, measured in the Figma file. | Component | Material 3 | iOS | What differs | | --- | --- | --- | --- | | Toggle | M3 / Switch, 52 × 32 | iOS / Toggle, 64 × 28 | Material has a 24 thumb inside the track, iOS has a 38 × 24 knob that becomes a glass lens when pressed | | Navigation | M3 / Navigation bar, 412 × 80, three to five items | iOS / Tab Bar, floating capsule 62 high, two to five tabs | Material is a full width bar with a separate 24 high Gesture Navigation component, iOS floats on glass | | Top bar | M3 / Top app bar, Small 64 high, Medium 112, Large 152 | iOS / Toolbar on a 44 high top bar | Material has four bar types: Small, Center-aligned, Medium and Large | | Dialog | M3 / Basic dialog, 304 wide at radius 24 | iOS / Alert, 300 wide at radius 32 | Material has Basic, List and Scrollable list dialogs, iOS draws the alert as glass | | Sheet | M3 / Bottom sheet 412 wide and Side Sheet 320 wide | iOS / Sheet - Full Screen | Material adds a side sheet for large screens | | List | M3 / List Item, 56, 72 or 88 high by Lines | iOS / List with a 44 minimum row | Material sets the row height by lines of text, iOS sets only a minimum | | Text field | M3 / Text Field, Filled or Outlined, 56 high | iOS / Text Field | Material has Enabled, Focused, Error and Disabled states | | Picker | M3 / Modal date picker 360 × 524, Dial and Keyboard time pickers | iOS / Date and time pickers | Material offers a dial and a keyboard variant of the time picker | | Chip | M3 / Chip, 32 high at radius 8 | No counterpart | The Apple pages have no chip | | Snackbar | M3 / Snackbar, 344 wide | No counterpart | The Apple pages have no snackbar | | Tooltip | M3 / Plain Tooltip and Rich Tooltip | No counterpart | The Apple pages have no tooltip | The Platform collection carries the shared numbers, one mode per platform. | Variable | android | ios-lg | | --- | --- | --- | | `grid/safe-area/top` | 52 | 62 | | `grid/safe-area/bottom` | 24 | 34 | | `platform/min-touch-target` | 48 | 44 | | `platform/bar/top-height` | 64 | 44 | | `platform/bar/bottom-height` | 64 | 49 | | `platform/list-row/min-height` | 56 | 44 | | `platform/control/corner` | 9999 | 8 | | `platform/sheet/corner` | 28 | 12 | | `platform/dialog/corner` | 28 | 12 | | `platform/switch/track-width` | 52 | 64 | | `platform/switch/track-height` | 32 | 28 | The minimum touch target is 48 on android and 44 on every iOS mode. Both values are bound to `platform/min-touch-target`, so one list row obeys both platforms without a second copy. The iOS side is on the [iOS page](https://www.appetiteui.com/docs/ios). ## Tokens and state layers Every Material role in Platform Bridge is prefixed M3/sys/: 32 color roles, 6 corner steps, 15 typescale steps and 7 state opacities. | Role | Brand | System | | --- | --- | --- | | `color/primary` | #155DFC | #6750A4 | | `color/secondary-container` | #DBEAFE | #E8DEF8 | | `color/error` | #FB2C36 | #B3261E | | `color/surface` | #FFFFFF | #FEF7FF | | `color/on-surface` | #0E0E0F | #1D1B20 | | `color/on-surface-variant` | #48484A | #49454F | | `color/outline` | #8E8E93 | #79747E | | `color/surface-container-high` | #F4F5F5 | #ECE6F0 | | `color/surface-container-highest` | #E9E9EA | #E6E0E9 | | Role | Brand | System | | --- | --- | --- | | `color/primary` | #2B7FFF | #D0BCFF | | `color/secondary-container` | #0D2673 | #4A4458 | | `color/error` | #FB2C36 | #F2B8B5 | | `color/surface` | #0E0E0F | #141218 | | `color/on-surface` | #FFFFFF | #E6E0E9 | | `color/on-surface-variant` | #C7C7CC | #CAC4D0 | | `color/outline` | #AEAEB2 | #938F99 | | `color/surface-container-high` | #242427 | #2B2930 | | `color/surface-container-highest` | #48484A | #36343B | | Shape role | Brand | System | | --- | --- | --- | | `corner-extra-small` | 4 | 4 | | `corner-small` | 8 | 8 | | `corner-medium` | 12 | 12 | | `corner-large` | 16 | 16 | | `corner-extra-large` | 24 | 28 | | `corner-full` | 9999 | 9999 | One of the six corner steps moves between the modes: corner-extra-large routes through `dimensions/radius/*` in Brand and holds Material's own 28 in System. Typescale binds the same way: `typescale/body-large` is `typography/fontSize/base` in Brand and 16 in System. | State opacity | Both modes | Covers | | --- | --- | --- | | `state/hover-opacity` | 8 | Pointer over a target | | `state/focus-opacity` | 10 | Keyboard focus | | `state/pressed-opacity` | 10 | Touch down | | `state/disabled-container-opacity` | 12 | A disabled container | | `state/dragged-opacity` | 16 | An item being moved | | `state/scrim-opacity` | 32 | The wash behind a dialog | | `state/disabled-content-opacity` | 38 | A disabled label or icon | The seven opacities are the one part of the mirror the Bridge leaves alone: bare numbers, the same in both modes, because a state layer is a rule about interaction and brand does not decide it. They bind straight to node opacity on `_M3 / State layer`, over a fill of `M3/sys/color/on-surface`. Values read in the Figma file on October 2, 2026, from the component `_M3 / State layer`, node 10166:478. Material Design is a trademark of Google LLC. iOS, SwiftUI, SF Pro and SF Symbols are trademarks of Apple Inc. Appetite UI is not affiliated with, endorsed by or sponsored by either; platform names here describe compatibility. These patterns are referenced under CC BY 4.0 and redrawn in Appetite UI's own geometry, on its own tokens, in Inter, with Lucide icons. Material Symbols are not bundled: add them yourself and they fall under the Apache License 2.0.