Files
dees-catalog-mobile/readme.md

13 KiB
Raw Permalink Blame History

@design.estate/dees-catalog-mobile

A mobile-optimized web component catalog for building cross-platform business applications with touch-first UI components. Built on Lit and designed for PWAs, native app wrappers, and mobile web.

Issue Reporting and Security

For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.

Install

npm install @design.estate/dees-catalog-mobile
# or
pnpm add @design.estate/dees-catalog-mobile

📱 Features

  • Touch-First Design 44px minimum touch targets, tap feedback, and gesture-friendly interactions
  • Dark/Light Theme Support Automatic theme adaptation using cssManager.bdTheme()
  • iOS Safe Area Support Proper handling of notches and home indicators
  • iOS Keyboard Detection Automatic layout adjustments when soft keyboard appears
  • Smooth Animations Native-feeling slide transitions for view navigation
  • TypeScript Native Full type definitions and excellent IDE support
  • Lucide Icons 1000+ icons with intelligent caching

🧩 Components

UI Components

<dees-mobile-button>

Versatile button with multiple variants and sizes.

<dees-mobile-button variant="primary" size="md">Click Me</dees-mobile-button>
<dees-mobile-button variant="destructive" loading>Processing...</dees-mobile-button>
<dees-mobile-button variant="ghost" icon><dees-mobile-icon icon="menu"></dees-mobile-icon></dees-mobile-button>
Property Type Default Description
variant 'default' | 'primary' | 'secondary' | 'outline' | 'ghost' | 'destructive' | 'link' 'default' Button style variant
size 'sm' | 'md' | 'lg' 'md' Button size
disabled boolean false Disable the button
loading boolean false Show loading spinner
icon boolean false Icon-only mode (square button)
type 'button' | 'submit' | 'reset' 'button' HTML button type

<dees-mobile-icon>

Lucide icon integration with smart caching.

<dees-mobile-icon icon="home" size="24" color="#3b82f6"></dees-mobile-icon>
<dees-mobile-icon icon="settings" size="32"></dees-mobile-icon>
Property Type Default Description
icon string '' Lucide icon name (e.g., 'home', 'settings', 'user')
size string | number '24' Icon size in pixels
color string 'currentColor' Icon color
strokeWidth string | number '2' Stroke width

<dees-mobile-header>

App header with flexible slot-based layout.

<dees-mobile-header title="My App" subtitle="Dashboard">
  <dees-mobile-button slot="left-action" icon variant="ghost">
    <dees-mobile-icon icon="menu"></dees-mobile-icon>
  </dees-mobile-button>
  <dees-mobile-button slot="actions" icon variant="ghost">
    <dees-mobile-icon icon="search"></dees-mobile-icon>
  </dees-mobile-button>
</dees-mobile-header>
Property Type Default Description
title string '' Header title
subtitle string '' Optional subtitle

Slots: left-action, content, middle, actions


<dees-mobile-modal>

Centered modal dialog with backdrop.

<dees-mobile-modal .open=${this.showModal} title="Confirm Action" @close=${() => this.showModal = false}>
  <p>Are you sure you want to proceed?</p>
  <div slot="footer">
    <dees-mobile-button variant="outline" @click=${() => this.showModal = false}>Cancel</dees-mobile-button>
    <dees-mobile-button variant="primary" @click=${this.confirm}>Confirm</dees-mobile-button>
  </div>
</dees-mobile-modal>
Property Type Default Description
open boolean false Controls visibility
title string '' Modal title
showCloseButton boolean true Show close button in header

Events: close


<dees-mobile-actionsheet>

iOS-style bottom action sheet.

<dees-mobile-actionsheet
  title="Choose an action"
  .options=${[
    { id: 'edit', icon: 'pencil', title: 'Edit', subtitle: 'Modify this item' },
    { id: 'share', icon: 'share', title: 'Share' },
    { id: 'delete', icon: 'trash-2', iconColor: '#dc2626', title: 'Delete' }
  ]}
  @select=${(e) => console.log('Selected:', e.detail.id)}
  @close=${() => this.hideActionSheet()}
></dees-mobile-actionsheet>
Property Type Default Description
title string '' Sheet title
options IActionSheetOption[] [] Action options
cancelText string 'Cancel' Cancel button text

Events: select, close


<dees-mobile-toast>

Toast notification system.

<dees-mobile-toast
  .open=${this.showToast}
  message="Item saved successfully!"
  type="success"
  duration="3000"
></dees-mobile-toast>

Layout Components

<dees-mobile-navigation>

Bottom tab navigation bar with badge support.

<dees-mobile-navigation
  .activeTab=${'home'}
  .tabs=${[
    { id: 'home', icon: 'home', label: 'Home' },
    { id: 'search', icon: 'search', label: 'Search' },
    { id: 'notifications', icon: 'bell', label: 'Alerts', badge: 5 },
    { id: 'profile', icon: 'user', label: 'Profile' }
  ]}
  @tab-change=${(e) => this.activeTab = e.detail.tab}
></dees-mobile-navigation>
Property Type Default Description
activeTab string '' Currently active tab ID
tabs INavigationTab[] [] Array of tab definitions

Events: tab-change


<dees-mobile-applayout>

Full-screen app layout with iOS keyboard handling.

<dees-mobile-applayout>
  <dees-mobile-header slot="header" title="My App"></dees-mobile-header>

  <div slot="content">
    <!-- Your app content here -->
  </div>

  <dees-mobile-navigation slot="navigation" .tabs=${this.tabs}></dees-mobile-navigation>
</dees-mobile-applayout>

Slots: header, content, navigation


<dees-mobile-viewstack> + <dees-mobile-view>

Stack-based navigation with smooth slide transitions. Perfect for drill-down interfaces (lists → detail → sub-detail).

<dees-mobile-viewstack initial-view="lists" @view-changed=${this.handleViewChange}>
  <dees-mobile-view view-id="lists">
    <my-lists-view @item-click=${(e) => this.viewstack.pushView('detail')}></my-lists-view>
  </dees-mobile-view>

  <dees-mobile-view view-id="detail">
    <my-detail-view @back=${() => this.viewstack.popView()}></my-detail-view>
  </dees-mobile-view>

  <dees-mobile-view view-id="subdetail">
    <my-subdetail-view></my-subdetail-view>
  </dees-mobile-view>
</dees-mobile-viewstack>

Viewstack API:

const viewstack = document.querySelector('dees-mobile-viewstack');

// Navigate forward (slides in from right)
await viewstack.pushView('detail');

// Navigate back (slides out to right)
await viewstack.popView();

// Replace current view (no animation)
viewstack.replaceView('other');

// Go back to root view
await viewstack.goToRoot(true); // animated
viewstack.goToRoot(false);      // instant

// Properties
viewstack.currentView;   // Current view ID
viewstack.stackDepth;    // Number of views in stack
viewstack.canGoBack;     // true if stack depth > 1

Events: view-changed, transition-start, transition-end, navigate-back


Input Components

<dees-mobile-input>

Form input with label, validation, and iOS zoom prevention.

<dees-mobile-input
  label="Email Address"
  type="email"
  placeholder="you@example.com"
  required
  autocomplete="email"
  @input=${(e) => console.log(e.detail.value)}
></dees-mobile-input>

<dees-mobile-input
  label="Password"
  type="password"
  error="Password must be at least 8 characters"
></dees-mobile-input>
Property Type Default Description
type 'text' | 'email' | 'password' | 'number' | 'tel' | 'url' | 'search' 'text' Input type
label string '' Label text
placeholder string '' Placeholder text
value string '' Input value
disabled boolean false Disable input
required boolean false Mark as required
error string '' Error message
autocomplete string '' Autocomplete hint

Events: input, change, input-focus, input-blur


🎨 Theming

Components automatically adapt to dark/light themes. Theme switching is handled via CSS variables and cssManager.bdTheme():

// In your component styles
css`
  .my-element {
    background: ${cssManager.bdTheme('#ffffff', '#09090b')};
    color: ${cssManager.bdTheme('#09090b', '#fafafa')};
    border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
  }
`

CSS Variables

Components use these CSS custom properties:

:root {
  --dees-primary: #3b82f6;
  --dees-background: #ffffff;
  --dees-foreground: #09090b;
  --dees-muted-foreground: #71717a;
  --dees-border: #e4e4e7;
  --dees-ring: #3b82f6;
  --dees-danger: #dc2626;
  --dees-radius: 0.5rem;
  --dees-radius-lg: 0.75rem;
  --dees-transition-fast: 150ms;
  --safe-area-inset-bottom: env(safe-area-inset-bottom, 0px);
}

📦 Full Example

import {
  DeesMobileButton,
  DeesMobileHeader,
  DeesMobileNavigation,
  DeesMobileViewstack,
  DeesMobileView,
  DeesMobileInput,
} from '@design.estate/dees-catalog-mobile';

// All components auto-register. Just use them in your templates:
const template = html`
  <dees-mobile-applayout>
    <dees-mobile-header slot="header" title="My App"></dees-mobile-header>

    <dees-mobile-viewstack slot="content" initial-view="home">
      <dees-mobile-view view-id="home">
        <div class="home-content">
          <h1>Welcome!</h1>
          <dees-mobile-button variant="primary" @click=${() => viewstack.pushView('settings')}>
            Go to Settings
          </dees-mobile-button>
        </div>
      </dees-mobile-view>

      <dees-mobile-view view-id="settings">
        <div class="settings-content">
          <dees-mobile-input label="Username" placeholder="Enter username"></dees-mobile-input>
          <dees-mobile-button @click=${() => viewstack.popView()}>Back</dees-mobile-button>
        </div>
      </dees-mobile-view>
    </dees-mobile-viewstack>

    <dees-mobile-navigation
      slot="navigation"
      .activeTab=${'home'}
      .tabs=${[
        { id: 'home', icon: 'home', label: 'Home' },
        { id: 'settings', icon: 'settings', label: 'Settings' },
      ]}
    ></dees-mobile-navigation>
  </dees-mobile-applayout>
`;

🛠️ Development

# Install dependencies
pnpm install

# Start development server with wcctools
pnpm run watch

# Build for production
pnpm run build

# Run tests
pnpm test

This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the license file.

Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

Trademarks

This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.

Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.

Company Information

Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany

For any legal inquiries or further information, please contact us via email at hello@task.vc.

By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.