This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Patterns

Small semantic HTML compositions built from native elements and CSS.

1 - accordion

Expandable content sections

Use an accessibly named section around native details elements. Give sibling items the same name when opening one item should close the others. The semantic structure needs no component class.

<section aria-label="Sections">
  <details name="sections" open>
    <summary>Section 1</summary>
    <div>Content for section 1</div>
  </details>
</section>

Omit name to allow more than one section to remain open.

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Accordion</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="accordion-demo">
    <section class="visual-example" aria-label="Shipping questions">
      <details name="shipping-questions" open>
        <summary>What are your shipping options?</summary>
        <div>
          We offer standard (5-7 days), express (2-3 days), and overnight
          shipping. Free shipping on international orders.
        </div>
      </details>
      <details name="shipping-questions">
        <summary>What is your return policy?</summary>
        <div>
          Returns are accepted within 30 days. Items must be unused and in their
          original packaging.
        </div>
      </details>
      <details name="shipping-questions">
        <summary>How can I contact customer support?</summary>
        <div>Reach us by email, live chat, or phone during business hours.</div>
      </details>
    </section>
  </body>
</html>

State Variants

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Accordion State Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    data-example="accordion-basic accordion-disabled accordion-multiple"
  >
    <main class="accordion-workflow-grid">
      <section
        class="accordion-workflow-section"
        aria-labelledby="accordion-basic-title"
      >
        <h2 id="accordion-basic-title">Account help</h2>
        <section aria-label="Account help questions">
          <details name="account-help" open>
            <summary>How do I reset my password?</summary>
            <div>
              Click Forgot Password on the login page, enter your email address,
              and we'll send you a reset link that expires in 24 hours.
            </div>
          </details>
          <details name="account-help">
            <summary>Can I change my subscription plan?</summary>
            <div>
              You can upgrade or downgrade your plan at any time from your
              account settings.
            </div>
          </details>
          <details name="account-help">
            <summary>What payment methods do you accept?</summary>
            <div>We accept major credit cards, PayPal, and bank transfers.</div>
          </details>
        </section>
      </section>
      <section
        class="accordion-workflow-section"
        aria-labelledby="accordion-disabled-title"
      >
        <h2 id="accordion-disabled-title">Availability</h2>
        <section aria-label="Feature availability questions">
          <details name="availability">
            <summary>Can I access my account history?</summary>
            <div>
              Your complete account history is available from the dashboard.
            </div>
          </details>
          <details name="availability" inert>
            <summary>Premium feature information</summary>
            <div>Upgrade your plan to access premium feature information.</div>
          </details>
          <details name="availability">
            <summary>How do I update my email address?</summary>
            <div>
              Update it in account settings and confirm the verification email.
            </div>
          </details>
        </section>
      </section>
      <section
        class="accordion-workflow-section accordion-workflow-wide"
        aria-labelledby="accordion-multiple-title"
      >
        <h2 id="accordion-multiple-title">Settings</h2>
        <section aria-label="Settings questions">
          <details open>
            <summary>Notification Settings</summary>
            <div>
              Choose email alerts or push notifications for mobile devices.
            </div>
          </details>
          <details>
            <summary>Privacy &amp; Security</summary>
            <div>
              Enable two-factor authentication, review active sessions, and
              configure data sharing.
            </div>
          </details>
          <details>
            <summary>Billing &amp; Subscription</summary>
            <div>View your plan, payment history, and upcoming invoices.</div>
          </details>
        </section>
      </section>
    </main>
  </body>
</html>

Layout Variants

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Accordion Layout Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    data-example="accordion-borders accordion-card accordion-rtl"
  >
    <main class="accordion-workflow-grid accordion-layout-workflows">
      <section
        class="accordion-workflow-section"
        aria-labelledby="accordion-borders-title"
      >
        <h2 id="accordion-borders-title">Billing questions</h2>
        <section class="accordion-bordered" aria-label="Billing questions">
          <details name="billing" open>
            <summary>How does billing work?</summary>
            <div>
              Billing is charged at the beginning of each monthly or annual
              cycle, and you can cancel anytime.
            </div>
          </details>
          <details name="billing">
            <summary>Is my data secure?</summary>
            <div>
              Data is encrypted at rest and in transit using industry-standard
              protocols.
            </div>
          </details>
          <details name="billing">
            <summary>What integrations do you support?</summary>
            <div>
              Connect popular tools or build custom integrations with our API.
            </div>
          </details>
        </section>
      </section>
      <article
        class="accordion-card-demo card"
        aria-labelledby="accordion-card-title"
      >
        <header>
          <h2 id="accordion-card-title">Subscription &amp; Billing</h2>
          <p>Common questions about plans, payments, and cancellations.</p>
        </header>
        <section>
          <section aria-label="Subscription and billing questions">
            <details name="subscription" open>
              <summary>What subscription plans do you offer?</summary>
              <div>
                Choose Starter, Professional, or Enterprise based on storage,
                API, and support needs.
              </div>
            </details>
            <details name="subscription">
              <summary>How does billing work?</summary>
              <div>
                Billing occurs automatically at the start of each cycle.
              </div>
            </details>
            <details name="subscription">
              <summary>How do I cancel my subscription?</summary>
              <div>
                Cancel from account settings with access through the current
                billing period.
              </div>
            </details>
          </section>
        </section>
      </article>
      <section
        class="accordion-workflow-section accordion-workflow-wide"
        dir="rtl"
        lang="ar"
        aria-labelledby="accordion-rtl-title"
      >
        <h2 id="accordion-rtl-title">الأسئلة الشائعة</h2>
        <section aria-label="الأسئلة الشائعة">
          <details name="arabic-faq" open>
            <summary>كيف يمكنني إعادة تعيين كلمة المرور؟</summary>
            <div>
              انقر على نسيت كلمة المرور في صفحة تسجيل الدخول، وسنرسل لك رابطًا
              لإعادة تعيينها.
            </div>
          </details>
          <details name="arabic-faq">
            <summary>هل يمكنني تغيير خطة الاشتراك الخاصة بي؟</summary>
            <div>يمكنك ترقية خطتك أو تخفيضها في أي وقت من إعدادات الحساب.</div>
          </details>
          <details name="arabic-faq">
            <summary>ما هي طرق الدفع التي تقبلونها؟</summary>
            <div>نقبل بطاقات الائتمان وPayPal والتحويلات المصرفية.</div>
          </details>
        </section>
      </section>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Named native details disclosures.

Anatomy

Root styling selector

  • section[aria-label]:has(> details)

Semantic structure

Use an accessibly named section around direct details children. Each item requires a direct summary followed by authored content. Apply the same name to sibling details for exclusive disclosure.

API

Attributes and state

AttributeAccessPurpose
inertAuthoredPrevents interaction while the component is hidden.
nameAuthoredAuthored HTML attribute or styling hook.
openAuthoredInitial or controlled open state.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Native details and summary own disclosure, focus, and keyboard behavior. Give sibling details the same name for an exclusive accordion, or omit name when several panels may remain open. AngularCSS registers no accordion directive.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use a direct summary as the accessible trigger for each details item. The browser exposes disclosure state and keyboard activation. Use inert only when an entire unavailable disclosure must be removed from interaction.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

2 - alert

Compact feedback blocks for status and context.

Use section[role="alert"] for important feedback blocks. The default presentation is neutral; add variant="destructive" for destructive feedback or override the AngularCSS color tokens for application-specific colors.

<section role="alert">
  <svg aria-hidden="true"><!-- optional icon --></svg>
  <h2>Saved!</h2>
  <p>Your profile was updated.</p>
  <div>
    <button ng-click="dismiss()">Dismiss</button>
  </div>
</section>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Alert</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="alert-demo">
    <div class="visual-example">
      <section aria-live="assertive" aria-atomic="true" role="alert">
        <svg
          aria-hidden="true"
          xmlns="http://www.w3.org/2000/svg"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
        >
          <circle cx="12" cy="12" r="10"></circle>
          <path d="M9 12l2 2 4-4"></path>
        </svg>

        <h2>Payment successful</h2>

        <p>
          Your payment of $29.99 has been processed. A receipt has been sent to
          your email address.
        </p>
      </section>

      <section aria-live="assertive" aria-atomic="true" role="alert">
        <svg
          aria-hidden="true"
          xmlns="http://www.w3.org/2000/svg"
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          stroke-width="2"
          stroke-linecap="round"
          stroke-linejoin="round"
        >
          <circle cx="12" cy="12" r="10"></circle>
          <path d="M12 16v-4" />
          <path d="M12 8h.01" />
        </svg>

        <h2>New feature available</h2>
        <p>
          We've added dark mode support. You can enable it in your account
          settings.
        </p>
      </section>
    </div>
  </body>
</html>

Variants And Composition

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Alert Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="darkModeEnabled=false"
    data-example="alert-action alert-basic alert-colors alert-destructive alert-rtl"
  >
    <main class="alert-workflow-grid">
      <section role="alert">
        <svg aria-hidden="true" viewBox="0 0 24 24" fill="none">
          <circle
            cx="12"
            cy="12"
            r="10"
            stroke="currentColor"
            stroke-width="2"
          />
          <path
            d="m9 12 2 2 4-4"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
          />
        </svg>
        <h2>Account updated successfully</h2>
        <p>
          Your profile information has been saved. Changes will be reflected
          immediately.
        </p>
      </section>

      <section aria-live="polite" role="alert">
        <h2>Dark mode is now available</h2>
        <p>Enable it under your profile settings to get started.</p>
        <button
          size="xs"
          type="button"
          ng-click="darkModeEnabled=true"
          ng-disabled="darkModeEnabled"
        >
          {{ darkModeEnabled ? 'Enabled' : 'Enable' }}
        </button>
      </section>

      <section variant="warning" role="alert">
        <svg aria-hidden="true" viewBox="0 0 24 24" fill="none">
          <path
            d="M10.3 2.9 1.8 17a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 2.9a2 2 0 0 0-3.4 0Z"
            stroke="currentColor"
            stroke-width="2"
            stroke-linejoin="round"
          />
          <path
            d="M12 9v4M12 17h.01"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
          />
        </svg>
        <h2>Your subscription will expire in 3 days.</h2>
        <p>
          Renew now to avoid service interruption or upgrade to a paid plan.
        </p>
      </section>

      <section variant="destructive" role="alert">
        <svg aria-hidden="true" viewBox="0 0 24 24" fill="none">
          <circle
            cx="12"
            cy="12"
            r="10"
            stroke="currentColor"
            stroke-width="2"
          />
          <path
            d="M12 8v4M12 16h.01"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
          />
        </svg>
        <h2>Payment failed</h2>
        <p>
          Your payment could not be processed. Check your payment method and try
          again.
        </p>
      </section>

      <section
        class="alert-rtl-demo"
        dir="rtl"
        lang="ar"
        aria-label="التنبيهات"
      >
        <section role="alert">
          <svg aria-hidden="true" viewBox="0 0 24 24" fill="none">
            <circle
              cx="12"
              cy="12"
              r="10"
              stroke="currentColor"
              stroke-width="2"
            />
            <path
              d="m9 12 2 2 4-4"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
          </svg>
          <h2>تم الدفع بنجاح</h2>
          <p>تمت معالجة دفعتك وإرسال إيصال إلى عنوان بريدك الإلكتروني.</p>
        </section>
        <section role="alert">
          <svg aria-hidden="true" viewBox="0 0 24 24" fill="none">
            <circle
              cx="12"
              cy="12"
              r="10"
              stroke="currentColor"
              stroke-width="2"
            />
            <path
              d="M12 16v-4M12 8h.01"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
            />
          </svg>
          <h2>ميزة جديدة متاحة</h2>
          <p>لقد أضفنا دعم الوضع الداكن ويمكنك تفعيله في إعدادات حسابك.</p>
        </section>
      </section>

      <output class="output alert-workflow-output">
        Dark mode: {{ darkModeEnabled ? 'enabled' : 'disabled' }}
      </output>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Semantic authored status content.

Anatomy

Root styling selector

  • [role="alert"]

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

AttributeAccessPurpose
aria-atomicAuthoredWhether an assistive technology announces the entire updated region.
aria-liveAuthoredAnnouncement priority for updates to a live region.
roleAuthoredExplicit semantic role when native HTML does not provide one.
variantAuthoredStatus presentation: info, success, warning, or destructive; omit for the default presentation.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Semantic authored status content. AngularCSS supplies styling without a runtime directive. Native HTML owns platform behavior; AngularTS owns application values, commands, and authored state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use the appropriate live-region or status semantics for dynamic feedback. Decorative feedback must stay hidden from assistive technology.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

3 - aspect-ratio

Fixed-ratio media wrapper

Set ratio on a figure and optionally override --ratio. Direct images, videos, and iframes fill the figure with object-fit: cover; applications may override that fit when media should not crop.

<figure ratio="16 / 9">
  <img src="photo.jpg" alt="Photo" />
</figure>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Aspect Ratio</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="aspect-ratio-demo">
    <figure ratio="16 / 9" class="visual-example">
      <img src="../../images/avatars/01.png" alt="Photo" />
    </figure>
  </body>
</html>

Ratios And Direction

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Aspect Ratio Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    data-example="aspect-ratio-portrait aspect-ratio-rtl aspect-ratio-square"
  >
    <main class="aspect-ratio-workflows">
      <figure
        ratio="9 / 16"
        class="aspect-ratio-portrait"
        aria-label="Portrait aspect ratio"
      >
        <img src="../../images/avatars/01.png" alt="Photo" />
      </figure>

      <figure
        ratio="1 / 1"
        class="aspect-ratio-square"
        aria-label="Square aspect ratio"
      >
        <img src="../../images/avatars/01.png" alt="Photo" />
      </figure>

      <figure class="aspect-ratio-rtl" dir="rtl" lang="ar">
        <figure ratio="16 / 9" aria-label="Landscape aspect ratio">
          <img src="../../images/avatars/01.png" alt="صورة" />
        </figure>
        <figcaption>منظر طبيعي جميل</figcaption>
      </figure>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. CSS aspect-ratio layout.

Anatomy

Root styling selector

  • figure[ratio]

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

AttributeAccessPurpose
ratioAuthoredAspect ratio: 1 / 1, 9 / 16, or 16 / 9; defaults to 16 / 9.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

VariablePurpose
--ratioRendered aspect ratio; defaults to 16 / 9.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

CSS aspect-ratio layout. AngularCSS supplies styling without a runtime directive. Native HTML owns platform behavior; AngularTS owns application values, commands, and authored state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Prefer semantic landmarks and native elements inside the layout. Any interactive handles or triggers must retain an accessible name and visible focus indicator.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

4 - avatar

User avatar, fallback, badge, and group primitives.

Use .avatar with a native image or authored fallback, plus an optional badge. Place adjacent avatars and a native output in one wrapper to form a group.

<span class="avatar" aria-label="Jane Doe">
  <span>JD</span>
  <output></output>
</span>

<span>
  <span class="avatar"><img src="avatar.jpg" alt="Alex Brown" /></span>
  <output>+3</output>
</span>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Avatar</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    data-example="avatar-badge avatar-basic avatar-demo avatar-group avatar-group-count"
  >
    <div class="visual-example">
      <span class="avatar">
        <img
          class="avatar-grayscale"
          src="../../images/avatars/01.png"
          alt="Profile portrait"
        />
        <span>CN</span>
      </span>
      <span class="avatar">
        <img src="../../images/avatars/02.png" alt="Profile portrait" />
        <span>ER</span>
        <output variant="success"></output>
      </span>
      <span class="avatar" aria-label="Jane Doe">
        <span>JD</span>
      </span>
      <span class="avatar-grayscale">
        <span class="avatar">
          <img src="../../images/avatars/01.png" alt="Profile portrait" />
          <span>CN</span>
        </span>
        <span class="avatar">
          <img src="../../images/avatars/03.png" alt="Profile portrait" />
          <span>LR</span>
        </span>
        <span class="avatar">
          <img src="../../images/avatars/04.png" alt="Profile portrait" />
          <span>ER</span>
        </span>
        <output>+3</output>
      </span>
    </div>
  </body>
</html>

Variants And Composition

Use size="sm", the default size, or size="lg". Badge icons, grouped counts, RTL layouts, and dropdown triggers compose from the same semantic parts without changing Avatar behavior.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Avatar Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="avatarAction = 'None'"
    data-example="avatar-badge-icon avatar-dropdown avatar-group-count-icon avatar-rtl avatar-size"
  >
    <main class="avatar-workflows">
      <section
        class="avatar-workflow-section"
        aria-labelledby="avatar-badge-heading"
      >
        <h2 id="avatar-badge-heading">Badge icon</h2>
        <div class="avatar-workflow-row" aria-label="Avatar badge icon">
          <span class="avatar">
            <img
              class="avatar-grayscale"
              src="../../images/avatars/02.png"
              alt="@pranathip"
            />
            <span>PP</span>
            <output>
              <svg
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
                aria-hidden="true"
              >
                <path d="M5 12h14" />
                <path d="M12 5v14" />
              </svg>
            </output>
          </span>
        </div>
      </section>

      <section
        class="avatar-workflow-section"
        aria-labelledby="avatar-count-heading"
      >
        <h2 id="avatar-count-heading">Group count icon</h2>
        <div class="avatar-grayscale" aria-label="Avatar group count icon">
          <span class="avatar">
            <img src="../../images/avatars/01.png" alt="@angularcss" />
            <span>CN</span>
          </span>
          <span class="avatar">
            <img src="../../images/avatars/03.png" alt="@maxleiter" />
            <span>LR</span>
          </span>
          <span class="avatar">
            <img src="../../images/avatars/04.png" alt="@evilrabbit" />
            <span>ER</span>
          </span>
          <output>
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
              aria-hidden="true"
            >
              <path d="M5 12h14" />
              <path d="M12 5v14" />
            </svg>
          </output>
        </div>
      </section>

      <section
        class="avatar-workflow-section"
        aria-labelledby="avatar-size-heading"
      >
        <h2 id="avatar-size-heading">Sizes</h2>
        <div
          class="avatar-workflow-row avatar-grayscale"
          aria-label="Avatar sizes"
        >
          <span size="sm" class="avatar">
            <img src="../../images/avatars/01.png" alt="@angularcss small" />
            <span>CN</span>
          </span>
          <span class="avatar">
            <img src="../../images/avatars/01.png" alt="@angularcss default" />
            <span>CN</span>
          </span>
          <span size="lg" class="avatar">
            <img src="../../images/avatars/01.png" alt="@angularcss large" />
            <span>CN</span>
          </span>
        </div>
      </section>

      <section
        class="avatar-workflow-section avatar-dropdown-stage"
        aria-labelledby="avatar-menu-heading"
      >
        <h2 id="avatar-menu-heading">Dropdown</h2>
        <div ng-dropdown-menu>
          <button
            type="button"
            variant="ghost"
            size="icon"
            class="avatar-dropdown-trigger"
            aria-label="Open user menu"
          >
            <span class="avatar">
              <img src="../../images/avatars/01.png" alt="AngularCSS" />
              <span>CN</span>
            </span>
          </button>
          <menu style="--menu-width: 8rem">
            <section>
              <button ng-click="avatarAction = 'Profile'">Profile</button>
              <button ng-click="avatarAction = 'Billing'">Billing</button>
              <button ng-click="avatarAction = 'Settings'">Settings</button>
            </section>
            <hr />
            <section>
              <button variant="destructive" ng-click="avatarAction = 'Log out'">
                Log out
              </button>
            </section>
          </menu>
        </div>
        <output class="avatar-workflow-output">
          Selected: {{ avatarAction }}
        </output>
      </section>

      <section
        class="avatar-workflow-section avatar-workflow-wide"
        aria-labelledby="avatar-rtl-heading"
        dir="rtl"
        lang="ar"
      >
        <h2 id="avatar-rtl-heading">اتجاه من اليمين إلى اليسار</h2>
        <div
          class="avatar-workflow-row avatar-rtl-demo"
          aria-label="صور رمزية من اليمين إلى اليسار"
        >
          <span class="avatar">
            <img
              class="avatar-grayscale"
              src="../../images/avatars/01.png"
              alt="@angularcss"
            />
            <span>CN</span>
          </span>
          <span class="avatar-rtl-badge avatar">
            <img src="../../images/avatars/04.png" alt="@evilrabbit" />
            <span>ER</span>
            <output variant="success"></output>
          </span>
          <span class="avatar-grayscale">
            <span class="avatar">
              <img src="../../images/avatars/01.png" alt="@angularcss" />
              <span>CN</span>
            </span>
            <span class="avatar">
              <img src="../../images/avatars/03.png" alt="@maxleiter" />
              <span>LR</span>
            </span>
            <span class="avatar">
              <img src="../../images/avatars/04.png" alt="@evilrabbit" />
              <span>ER</span>
            </span>
            <output></output>
          </span>
        </div>
      </section>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Native image and fallback composition.

Anatomy

Root styling selector

  • .avatar

Semantic structure

Apply .avatar to a wrapper containing either an image or authored fallback content. Badges are optional. Place adjacent avatars and a native output for the remaining count in one div or span; AngularCSS recognizes that group from its structure.

API

Attributes and state

AttributeAccessPurpose
sizeAuthoredAvatar size: sm or lg; omit for the default size.
variantAuthoredOptional direct output badge status: success; omit for the primary status color.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Avatar is a styling-only authored HTML pattern. Native img loading and alternative text remain browser behavior; use a fallback-only avatar when no image is available, or AngularTS structural directives when application state chooses between sources.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Give meaningful portrait images useful alternative text. Give fallback-only avatars an accessible name when initials are ambiguous, and keep decorative status badges out of repeated announcements.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

5 - badge

Inline status and metadata labels with semantic variants.

Use class="badge" on an inline element and set variant for appearance.

<span class="badge">Default</span>
<span variant="secondary" class="badge">Secondary</span>
<span variant="outline" class="badge">Outline</span>

For user-selected colors, use variant="custom" and set --badge-background. Browsers with contrast-color() choose a black or white foreground; set --badge-foreground when the application requires a specific contrast result.

<span variant="custom" class="badge" style="--badge-background: var(--cyan-9)">
  Custom
</span>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Badge</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="badge-demo">
    <div class="row visual-example">
      <span class="badge">Badge</span>
      <span variant="secondary" class="badge">Secondary</span>
      <span variant="destructive" class="badge">Destructive</span>
      <span variant="outline" class="badge">Outline</span>
      <span
        variant="custom"
        class="badge"
        style="--badge-background: var(--cyan-9)"
      >
        Custom
      </span>
    </div>
  </body>
</html>

Composition workflows

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Badge Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    data-example="badge-colors badge-icon badge-link badge-rtl badge-spinner badge-variants"
  >
    <main class="workflow-stack">
      <div class="workflow-row" aria-label="Badge variants">
        <span class="badge">Default</span>
        <span variant="secondary" class="badge">Secondary</span>
        <span variant="destructive" class="badge">Destructive</span>
        <span variant="outline" class="badge">Outline</span>
        <span variant="ghost" class="badge">Ghost</span>
      </div>

      <div class="workflow-row" aria-label="Badge custom colors">
        <span class="badge-color-blue badge">Blue</span>
        <span class="badge-color-green badge">Green</span>
        <span class="badge-color-sky badge">Sky</span>
        <span class="badge-color-purple badge">Purple</span>
        <span class="badge-color-red badge">Red</span>
      </div>

      <div class="workflow-row" aria-label="Badges with icons">
        <span variant="secondary" class="badge">
          <svg
            icon="inline-start"
            viewBox="0 0 24 24"
            fill="none"
            aria-hidden="true"
          >
            <path
              d="m9 12 2 2 4-4M12 3l2.2 1.5 2.7-.1.8 2.6 2.2 1.5-.9 2.5.9 2.5-2.2 1.5-.8 2.6-2.7-.1L12 21l-2.2-1.5-2.7.1-.8-2.6L4.1 15l.9-2.5-.9-2.5L6.3 7l.8-2.6 2.7.1L12 3Z"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
          </svg>
          Verified
        </span>
        <span variant="outline" class="badge">
          Bookmark
          <svg
            icon="inline-end"
            viewBox="0 0 24 24"
            fill="none"
            aria-hidden="true"
          >
            <path
              d="M6 4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18l-6-4-6 4V4Z"
              stroke="currentColor"
              stroke-width="2"
              stroke-linejoin="round"
            />
          </svg>
        </span>
        <a href="#link" class="badge">
          Open Link
          <svg
            icon="inline-end"
            viewBox="0 0 24 24"
            fill="none"
            aria-hidden="true"
          >
            <path
              d="M7 17 17 7M7 7h10v10"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
              stroke-linejoin="round"
            />
          </svg>
        </a>
      </div>

      <div class="workflow-row" aria-label="Badges with loading status">
        <span variant="destructive" class="badge">
          <svg
            icon="inline-start"
            aria-hidden="true"
            viewBox="0 0 24 24"
            fill="none"
            class="spinner"
          >
            <path
              d="M21 12a9 9 0 1 1-6.22-8.56"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
            />
          </svg>
          Deleting
        </span>
        <span variant="secondary" class="badge">
          Generating
          <svg
            icon="inline-end"
            aria-hidden="true"
            viewBox="0 0 24 24"
            fill="none"
            class="spinner"
          >
            <path
              d="M21 12a9 9 0 1 1-6.22-8.56"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
            />
          </svg>
        </span>
      </div>

      <div class="workflow-row" dir="rtl" aria-label="RTL badges">
        <span class="badge">شارة</span>
        <span variant="secondary" class="badge">ثانوي</span>
        <span variant="destructive" class="badge">مدمر</span>
        <span variant="outline" class="badge">مخطط</span>
      </div>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Styled inline authored content.

Anatomy

Root styling selector

  • .badge

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

AttributeAccessPurpose
iconAuthoredDirect icon position: inline-start or inline-end.
variantAuthoredPresentation: default, secondary, destructive, outline, ghost, or custom.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Styled inline authored content. AngularCSS supplies styling without a runtime directive. Native HTML owns platform behavior; AngularTS owns application values, commands, and authored state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use the appropriate live-region or status semantics for dynamic feedback. Decorative feedback must stay hidden from assistive technology.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

6 - breadcrumb

Page location navigation

Use a .breadcrumb navigation landmark with a native ordered list, links, separators, and aria-current="page" for the current location. The class distinguishes the trail from other navigation landmarks.

<nav aria-label="breadcrumb" class="breadcrumb">
  <ol>
    <li>
      <a href="#">Home</a>
    </li>
    <li aria-hidden="true">/</li>
    <li>
      <span aria-current="page">Docs</span>
    </li>
  </ol>
</nav>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Breadcrumb</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    data-example="breadcrumb-basic breadcrumb-link"
  >
    <nav aria-label="breadcrumb" class="breadcrumb">
      <ol>
        <li>
          <a href="#">Home</a>
        </li>
        <li aria-hidden="true">/</li>
        <li>
          <a href="#">Components</a>
        </li>
        <li aria-hidden="true">/</li>
        <li>
          <span aria-current="page">Breadcrumb</span>
        </li>
      </ol>
    </nav>
  </body>
</html>

Variants And Composition

Empty separator and ellipsis parts receive their standard icons. Author custom separator content directly, and compose dropdowns with the existing semantic Dropdown component.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Breadcrumb Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="breadcrumbSelection = 'None'; rtlBreadcrumbSelection = 'لا شيء'"
    data-example="breadcrumb-demo breadcrumb-dropdown breadcrumb-ellipsis breadcrumb-rtl breadcrumb-separator"
  >
    <main>
      <section aria-labelledby="breadcrumb-separator-heading">
        <h2 id="breadcrumb-separator-heading">Custom separator</h2>
        <nav aria-label="Custom separator breadcrumb" class="breadcrumb">
          <ol>
            <li>
              <a href="#home">Home</a>
            </li>
            <li aria-hidden="true">
              <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                <circle cx="12" cy="12" r="2.5" />
              </svg>
            </li>
            <li>
              <a href="#components">Components</a>
            </li>
            <li aria-hidden="true">
              <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                <circle cx="12" cy="12" r="2.5" />
              </svg>
            </li>
            <li>
              <span aria-current="page" aria-disabled="true">Breadcrumb</span>
            </li>
          </ol>
        </nav>
      </section>

      <section aria-labelledby="breadcrumb-ellipsis-heading">
        <h2 id="breadcrumb-ellipsis-heading">Ellipsis</h2>
        <nav aria-label="Ellipsis breadcrumb" class="breadcrumb">
          <ol>
            <li>
              <a href="#home">Home</a>
            </li>
            <li aria-hidden="true"></li>
            <li>
              <span aria-hidden="true">...</span>
            </li>
            <li aria-hidden="true"></li>
            <li>
              <a href="#components">Components</a>
            </li>
            <li aria-hidden="true"></li>
            <li>
              <span aria-current="page" aria-disabled="true">Breadcrumb</span>
            </li>
          </ol>
        </nav>
      </section>

      <section aria-labelledby="breadcrumb-demo-heading">
        <h2 id="breadcrumb-demo-heading">Collapsed trail</h2>
        <nav aria-label="Collapsed breadcrumb" class="breadcrumb">
          <ol>
            <li>
              <a href="#home">Home</a>
            </li>
            <li aria-hidden="true"></li>
            <li>
              <span ng-dropdown-menu>
                <button
                  type="button"
                  variant="ghost"
                  size="icon-sm"
                  aria-label="Toggle breadcrumb menu"
                >
                  <span aria-hidden="true">...</span>
                </button>
                <menu>
                  <section>
                    <button ng-click="breadcrumbSelection = 'Documentation'">
                      Documentation
                    </button>
                    <button ng-click="breadcrumbSelection = 'Themes'">
                      Themes
                    </button>
                    <button ng-click="breadcrumbSelection = 'GitHub'">
                      GitHub
                    </button>
                  </section>
                </menu>
              </span>
            </li>
            <li aria-hidden="true"></li>
            <li>
              <a href="#components">Components</a>
            </li>
            <li aria-hidden="true"></li>
            <li>
              <span aria-current="page" aria-disabled="true">Breadcrumb</span>
            </li>
          </ol>
        </nav>
        <output> Selected: {{ breadcrumbSelection }} </output>
      </section>

      <section aria-labelledby="breadcrumb-dropdown-heading">
        <h2 id="breadcrumb-dropdown-heading">Dropdown</h2>
        <nav aria-label="Dropdown breadcrumb" class="breadcrumb">
          <ol>
            <li>
              <a href="#home">Home</a>
            </li>
            <li aria-hidden="true">
              <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                <circle cx="12" cy="12" r="2.5" />
              </svg>
            </li>
            <li>
              <span ng-dropdown-menu>
                <button type="button">
                  Components
                  <svg
                    icon="inline-end"
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m6 9 6 6 6-6" />
                  </svg>
                </button>
                <menu>
                  <section>
                    <button>Documentation</button>
                    <button>Themes</button>
                    <button>GitHub</button>
                  </section>
                </menu>
              </span>
            </li>
            <li aria-hidden="true">
              <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                <circle cx="12" cy="12" r="2.5" />
              </svg>
            </li>
            <li>
              <span aria-current="page" aria-disabled="true">Breadcrumb</span>
            </li>
          </ol>
        </nav>
      </section>

      <section aria-labelledby="breadcrumb-rtl-heading" dir="rtl" lang="ar">
        <h2 id="breadcrumb-rtl-heading">اتجاه من اليمين إلى اليسار</h2>
        <nav aria-label="مسار التنقل" class="breadcrumb">
          <ol>
            <li>
              <a href="#home">الرئيسية</a>
            </li>
            <li aria-hidden="true">
              <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                <circle cx="12" cy="12" r="2.5" />
              </svg>
            </li>
            <li>
              <span ng-dropdown-menu>
                <button type="button">
                  المكونات
                  <svg
                    icon="inline-end"
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                    aria-hidden="true"
                  >
                    <path d="m6 9 6 6 6-6" />
                  </svg>
                </button>
                <menu>
                  <section>
                    <button ng-click="rtlBreadcrumbSelection = 'التوثيق'">
                      التوثيق
                    </button>
                    <button ng-click="rtlBreadcrumbSelection = 'السمات'">
                      السمات
                    </button>
                    <button ng-click="rtlBreadcrumbSelection = 'جيت هاب'">
                      جيت هاب
                    </button>
                  </section>
                </menu>
              </span>
            </li>
            <li aria-hidden="true">
              <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                <circle cx="12" cy="12" r="2.5" />
              </svg>
            </li>
            <li>
              <span aria-current="page" aria-disabled="true">مسار التنقل</span>
            </li>
          </ol>
        </nav>
        <output> المحدد: {{ rtlBreadcrumbSelection }} </output>
      </section>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Native navigation and list composition.

Anatomy

Root styling selector

  • .breadcrumb

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

AttributeAccessPurpose
aria-currentAuthoredCurrent item or date state.
dirAuthoredText and interaction direction: ltr or rtl.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Native navigation and list composition. AngularCSS supplies styling without a runtime directive. Native HTML owns platform behavior; AngularTS owns application values, commands, and authored state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use semantic navigation landmarks and links. Expose the current destination with aria-current and keep keyboard order consistent with visual order.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

7 - button-group

Layout primitive for visually connected buttons and form controls.

Use fieldset[role="group"] around related commands or form controls. Set orientation="vertical" for stacked groups. Use Toggle Group when the controls represent one or more selectable values.

<fieldset role="group">
  <button>One</button>
  <hr />
  <button>Two</button>
</fieldset>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Button Group</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="buttonGroupAction = 'None'"
    data-example="button-group-demo button-group-orientation separator button-group-size button-group-split"
  >
    <main class="visual-example">
      <section aria-label="Button group sizes">
        <div aria-label="State ownership" role="group">
          <button
            id="button-group-unmanaged"
            type="button"
            variant="outline"
            size="sm"
          >
            Small
          </button>
          <button
            id="button-group-managed"
            type="button"
            variant="outline"
            size="sm"
            aria-pressed="true"
          >
            Button
          </button>
          <button type="button" variant="outline" size="sm">Group</button>
          <button
            type="button"
            variant="outline"
            size="icon-sm"
            aria-label="Add small"
          >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              aria-hidden="true"
            >
              <path d="M5 12h14M12 5v14" />
            </svg>
          </button>
        </div>
        <div role="group">
          <button type="button" variant="outline">Default</button>
          <button type="button" variant="outline">Button</button>
          <button type="button" variant="outline">Group</button>
          <button
            type="button"
            variant="outline"
            size="icon"
            aria-label="Add default"
          >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              aria-hidden="true"
            >
              <path d="M5 12h14M12 5v14" />
            </svg>
          </button>
        </div>
        <div role="group">
          <button type="button" variant="outline" size="lg">Large</button>
          <button type="button" variant="outline" size="lg">Button</button>
          <button type="button" variant="outline" size="lg">Group</button>
          <button
            type="button"
            variant="outline"
            size="icon-lg"
            aria-label="Add large"
          >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              aria-hidden="true"
            >
              <path d="M5 12h14M12 5v14" />
            </svg>
          </button>
        </div>
      </section>

      <fieldset orientation="vertical" aria-label="Media controls" role="group">
        <button
          type="button"
          variant="outline"
          size="icon"
          aria-label="Increase"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            aria-hidden="true"
          >
            <path d="M5 12h14M12 5v14" />
          </svg>
        </button>
        <hr />
        <button
          type="button"
          variant="outline"
          size="icon"
          aria-label="Decrease"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            aria-hidden="true"
          >
            <path d="M5 12h14" />
          </svg>
        </button>
      </fieldset>

      <section aria-label="Button group compositions">
        <div role="group">
          <button
            type="button"
            variant="secondary"
            size="sm"
            ng-click="buttonGroupAction = 'Copy'"
          >
            Copy
          </button>
          <hr aria-orientation="vertical" />
          <button
            type="button"
            variant="secondary"
            size="sm"
            ng-click="buttonGroupAction = 'Paste'"
          >
            Paste
          </button>
        </div>
        <div role="group">
          <button
            type="button"
            variant="secondary"
            ng-click="buttonGroupAction = 'Button'"
          >
            Button
          </button>
          <hr aria-orientation="vertical" />
          <button
            type="button"
            variant="secondary"
            size="icon"
            aria-label="Add item"
            ng-click="buttonGroupAction = 'Add'"
          >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              aria-hidden="true"
            >
              <path d="M5 12h14M12 5v14" />
            </svg>
          </button>
        </div>
      </section>
      <output class="output">Action: {{ buttonGroupAction }}</output>
    </main>
  </body>
</html>

Composition Workflows

Button groups can connect nested groups, inputs, input groups, Select, Dropdown, and Popover triggers. Each composed component retains its own behavior and application state.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Button Group Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="toolbarAction = 'None'; searchTerm = ''; voiceEnabled = false; currency = '$'; rtlAction = 'لا شيء'"
    data-example="button-group-demo button-group-dropdown button-group-input button-group-input-group button-group-nested button-group-popover button-group-rtl button-group-select"
  >
    <main class="button-group-workflows">
      <section
        class="button-group-workflow-section button-group-menu-stage"
        aria-labelledby="button-group-toolbar-heading"
      >
        <h2 id="button-group-toolbar-heading">Toolbar</h2>
        <fieldset aria-label="Message actions" role="group">
          <div role="group">
            <button
              type="button"
              variant="outline"
              size="icon"
              aria-label="Go Back"
            >
            </button>
          </div>
          <div role="group">
            <button
              type="button"
              variant="outline"
              ng-click="toolbarAction = 'Archive'"
            >
              Archive
            </button>
            <button
              type="button"
              variant="outline"
              ng-click="toolbarAction = 'Report'"
            >
              Report
            </button>
          </div>
          <div role="group">
            <button
              type="button"
              variant="outline"
              ng-click="toolbarAction = 'Snooze'"
            >
              Snooze
            </button>
            <span ng-dropdown-menu>
              <button
                type="button"
                variant="outline"
                size="icon"
                aria-label="More Options"
              >
                •••
              </button>
              <menu align="end" style="--menu-width: 10rem">
                <section>
                  <button ng-click="toolbarAction = 'Mark as Read'">
                    Mark as Read
                  </button>
                  <button ng-click="toolbarAction = 'Archive'">Archive</button>
                  <button ng-click="toolbarAction = 'Snooze'">Snooze</button>
                </section>
                <span></span>
                <button
                  variant="destructive"
                  ng-click="toolbarAction = 'Trash'"
                >
                  Trash
                </button>
              </menu>
            </span>
          </div>
        </fieldset>
        <output class="button-group-output">
          Action: {{ toolbarAction }}
        </output>
      </section>

      <section
        class="button-group-workflow-section button-group-menu-stage"
        aria-labelledby="button-group-dropdown-heading"
      >
        <h2 id="button-group-dropdown-heading">Split dropdown</h2>
        <fieldset aria-label="Follow actions" role="group">
          <button type="button" variant="outline">Follow</button>
          <span ng-dropdown-menu>
            <button
              type="button"
              variant="outline"
              aria-label="More follow actions"
            ></button>
            <menu align="end" style="--menu-width: 11rem">
              <section>
                <button>Mute Conversation</button>
                <button>Mark as Read</button>
                <button>Report Conversation</button>
                <button>Block User</button>
                <button>Share Conversation</button>
                <button>Copy Conversation</button>
              </section>
              <span></span>
              <button variant="destructive">Delete Conversation</button>
            </menu>
          </span>
        </fieldset>
      </section>

      <section
        class="button-group-workflow-section"
        aria-labelledby="button-group-input-heading"
      >
        <h2 id="button-group-input-heading">Search input</h2>
        <div role="group">
          <input
            ng-model="searchTerm"
            placeholder="Search..."
            aria-label="Search query"
          />
          <button
            type="button"
            variant="outline"
            aria-label="Search"
            ng-click="toolbarAction = searchTerm || 'Search'"
          >
          </button>
        </div>
        <output class="button-group-output">
          Query: {{ searchTerm || 'Empty' }}
        </output>
      </section>

      <section
        class="button-group-workflow-section"
        aria-labelledby="button-group-nested-heading"
      >
        <h2 id="button-group-nested-heading">Nested input group</h2>
        <div role="group" style="--radius-md: var(--radius-full)">
          <div role="group">
            <button
              type="button"
              variant="outline"
              size="icon"
              aria-label="Add attachment"
            >
              +
            </button>
          </div>
          <div role="group">
            <div class="input-group">
              <input placeholder="Send a message..." aria-label="Message" />
              <span align="inline-end"></span>
            </div>
          </div>
        </div>
      </section>

      <section
        class="button-group-workflow-section"
        aria-labelledby="button-group-voice-heading"
      >
        <h2 id="button-group-voice-heading">Voice mode</h2>
        <div role="group" style="--radius-md: var(--radius-full)">
          <div role="group">
            <button
              type="button"
              variant="outline"
              size="icon"
              aria-label="Add message item"
            >
              +
            </button>
          </div>
          <div role="group">
            <div class="input-group">
              <input
                placeholder="{{ voiceEnabled ? 'Record and send audio...' : 'Send a message...' }}"
                ng-disabled="voiceEnabled"
                aria-label="Voice message"
              />
              <span align="inline-end">
                <button
                  type="button"
                  size="icon-xs"
                  aria-label="Voice Mode"
                  aria-pressed="{{ voiceEnabled }}"
                  ng-click="voiceEnabled = !voiceEnabled"
                >
                </button>
              </span>
            </div>
          </div>
        </div>
      </section>

      <section
        class="button-group-workflow-section button-group-popover-stage"
        aria-labelledby="button-group-popover-heading"
      >
        <h2 id="button-group-popover-heading">Popover</h2>
        <div role="group">
          <button type="button" variant="outline">◇ Copilot</button>
          <span>
            <button
              type="button"
              variant="outline"
              size="icon"
              aria-label="Open Popover"
              popovertarget="popover-button-group-workflows-1-content"
            >
            </button>
            <aside
              side="bottom"
              aria-label="Copilot task"
              class="button-group-popover-content"
              id="popover-button-group-workflows-1-content"
              align="center"
              popover
            >
              <header>
                <h3>Start a new task with Copilot</h3>
                <p>Describe your task in natural language.</p>
              </header>
              <label class="visually-hidden" for="copilot-task"
                >Task Description</label
              >
              <textarea id="copilot-task" placeholder="I need to..."></textarea>
              <p class="muted">Copilot will open a pull request for review.</p>
            </aside>
          </span>
        </div>
      </section>

      <section
        class="button-group-workflow-section button-group-select-stage"
        aria-labelledby="button-group-select-heading"
      >
        <h2 id="button-group-select-heading">Currency select</h2>
        <div role="group">
          <div role="group">
            <select aria-label="Currency" ng-model="currency">
              <option value="$">$ US Dollar</option>
              <option value="€">€ Euro</option>
              <option value="£">£ British Pound</option>
            </select>
            <input
              placeholder="10.00"
              inputmode="numeric"
              aria-label="Amount"
            />
          </div>
          <div role="group">
            <button
              type="button"
              variant="outline"
              size="icon"
              aria-label="Send"
            >
            </button>
          </div>
        </div>
      </section>

      <section
        class="button-group-workflow-section button-group-menu-stage button-group-workflow-wide"
        aria-labelledby="button-group-rtl-heading"
        dir="rtl"
        lang="ar"
      >
        <h2 id="button-group-rtl-heading">اتجاه من اليمين إلى اليسار</h2>
        <fieldset aria-label="إجراءات الرسالة" role="group">
          <div role="group">
            <button type="button" variant="outline">أرشفة</button>
            <button type="button" variant="outline">تقرير</button>
          </div>
          <div role="group">
            <button type="button" variant="outline">تأجيل</button>
            <span ng-dropdown-menu>
              <button
                type="button"
                variant="outline"
                size="icon"
                aria-label="المزيد من الخيارات"
              >
                •••
              </button>
              <menu align="end" style="--menu-width: 10rem">
                <button ng-click="rtlAction = 'وضع علامة كمقروء'">
                  وضع علامة كمقروء
                </button>
                <button ng-click="rtlAction = 'أرشفة'">أرشفة</button>
                <span></span>
                <button
                  variant="destructive"
                  ng-click="rtlAction = 'سلة المهملات'"
                >
                  سلة المهملات
                </button>
              </menu>
            </span>
          </div>
        </fieldset>
        <output class="button-group-output"> الإجراء: {{ rtlAction }} </output>
      </section>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Grouped native actions.

Anatomy

Root styling selector

  • [role="group"]

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

AttributeAccessPurpose
aria-orientationAuthoredUse vertical on a direct separator when it divides controls along the inline axis.
orientationAuthoredGroup layout: vertical; omit for the horizontal layout.
roleAuthoredExplicit semantic role when native HTML does not provide one.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Grouped native actions. AngularCSS supplies styling without a runtime directive. Native HTML owns platform behavior; AngularTS owns application values, commands, and authored state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use a native button whenever the control performs an action. Keep an accessible name, preserve visible focus, and use disabled for unavailable native controls.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

8 - card

Sectioned content container using semantic parts.

Use article.card with optional semantic header, content, footer, and action regions. Direct headers, headings, and header paragraphs need no part classes.

<article class="card">
  <header>
    <h2>Title</h2>
    <p>Optional description</p>
    <menu>Action</menu>
  </header>
  <section>Content</section>
  <footer>Footer</footer>
</article>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Card</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="card-demo">
    <article class="visual-example card">
      <header>
        <h2>Login to your account</h2>
        <p>Enter your email below to login to your account</p>
        <menu>
          <button variant="link" type="button">Sign Up</button>
        </menu>
      </header>
      <section>
        <form class="card-form" id="login-form">
          <div class="card-field">
            <label for="card-email">Email</label>
            <input
              id="card-email"
              type="email"
              placeholder="m@example.com"
              required
            />
          </div>
          <div class="card-field">
            <div class="card-label-row">
              <label for="card-password">Password</label>
              <a href="#forgot-password">Forgot your password?</a>
            </div>
            <input id="card-password" type="password" required />
          </div>
        </form>
      </section>
      <footer class="card-footer-stacked">
        <button type="submit" form="login-form">Login</button>
        <button variant="outline" type="button">Login with Google</button>
      </footer>
    </article>
  </body>
</html>

Image And RTL

Card content remains ordinary semantic HTML. Use local images, logical CSS properties, and AngularTS form or command directives for application state.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Card Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="cardAction='No event selected'; rtl={email:'',password:'',status:'جاهز'}; smallCardAction='No report action'"
    data-example="card-image card-rtl card-small"
  >
    <main class="card-workflows" aria-label="Card reference workflows">
      <section class="card-workflow" aria-labelledby="card-image-heading">
        <h2 id="card-image-heading">Image card</h2>
        <article class="card-image-card card">
          <div class="card-image-overlay" aria-hidden="true"></div>
          <img
            class="card-cover-image"
            src="../../images/avatars/01.png"
            alt="Abstract event cover"
          />
          <header>
            <menu>
              <span variant="secondary" class="badge">Featured</span>
            </menu>
            <h2>Design systems meetup</h2>
            <p>
              A practical talk on component APIs, accessibility, and shipping
              faster.
            </p>
          </header>
          <footer>
            <button
              type="button"
              class="card-full-button"
              ng-click="cardAction='Viewing Design systems meetup'"
            >
              View Event
            </button>
          </footer>
        </article>
        <output class="card-workflow-output">{{ cardAction }}</output>
      </section>

      <section
        class="card-workflow"
        aria-labelledby="card-rtl-heading"
        dir="rtl"
        lang="ar"
      >
        <h2 id="card-rtl-heading">بطاقة من اليمين إلى اليسار</h2>
        <article class="card-rtl-card card" dir="rtl">
          <header>
            <h2>تسجيل الدخول إلى حسابك</h2>
            <p>أدخل بريدك الإلكتروني أدناه لتسجيل الدخول إلى حسابك</p>
            <menu>
              <button
                variant="link"
                type="button"
                ng-click="rtl.status='إنشاء حساب جديد'"
              >
                إنشاء حساب
              </button>
            </menu>
          </header>
          <section>
            <form
              class="card-form"
              id="rtl-login-form"
              ng-submit="rtl.status='تم تسجيل الدخول باسم ' + rtl.email"
            >
              <div class="card-field">
                <label for="card-email-rtl">البريد الإلكتروني</label>
                <input
                  id="card-email-rtl"
                  type="email"
                  placeholder="m@example.com"
                  ng-model="rtl.email"
                  required
                />
              </div>
              <div class="card-field">
                <div class="card-label-row">
                  <label for="card-password-rtl">كلمة المرور</label>
                  <a href="#forgot-password-rtl">نسيت كلمة المرور؟</a>
                </div>
                <input
                  id="card-password-rtl"
                  type="password"
                  ng-model="rtl.password"
                  required
                />
              </div>
            </form>
          </section>
          <footer class="card-footer-stacked">
            <button type="submit" form="rtl-login-form">تسجيل الدخول</button>
            <button
              variant="outline"
              type="button"
              ng-click="rtl.status='متابعة باستخدام Google'"
            >
              تسجيل الدخول باستخدام Google
            </button>
          </footer>
        </article>
        <output class="card-workflow-output"> الحالة: {{ rtl.status }} </output>
      </section>

      <section class="card-workflow" aria-labelledby="card-small-heading">
        <h2 id="card-small-heading">Small card</h2>
        <article size="sm" class="card-small-card card">
          <header>
            <h2>Scheduled reports</h2>
            <p>Weekly snapshots. No more manual exports.</p>
          </header>
          <section>
            <ul class="card-feature-list">
              <li>
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  aria-hidden="true"
                >
                  <path d="m9 18 6-6-6-6" /></svg
                ><span>Choose a schedule (daily, or weekly).</span>
              </li>
              <li>
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  aria-hidden="true"
                >
                  <path d="m9 18 6-6-6-6" /></svg
                ><span>Send to channels or specific teammates.</span>
              </li>
              <li>
                <svg
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  aria-hidden="true"
                >
                  <path d="m9 18 6-6-6-6" /></svg
                ><span>Include charts, tables, and key metrics.</span>
              </li>
            </ul>
          </section>
          <footer class="card-footer-stacked">
            <button
              size="sm"
              type="button"
              ng-click="smallCardAction='Scheduled reports setup'"
            >
              Set up scheduled reports
            </button>
            <button
              variant="outline"
              size="sm"
              type="button"
              ng-click="smallCardAction='Showing report updates'"
            >
              See what's new
            </button>
          </footer>
        </article>
        <output class="card-workflow-output">{{ smallCardAction }}</output>
      </section>
    </main>
  </body>
</html>

Section States

Card sections are optional. CSS adapts spacing to the authored sections and size="sm" attribute; no directive runs for a card.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Card State Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak>
    <main class="component-state-grid" aria-label="Card state contracts">
      <section
        class="component-state-section"
        aria-labelledby="complete-card-title"
      >
        <h2 id="complete-card-title">Complete card</h2>
        <article aria-label="Complete card" class="card">
          <header>
            <h2>Quarterly planning</h2>
            <p>Review the agenda before Monday.</p>
            <menu>
              <button variant="ghost" size="sm" type="button">Edit</button>
            </menu>
          </header>
          <section>Four topics are ready for review.</section>
          <footer>Updated today</footer>
        </article>
      </section>

      <section
        class="component-state-section"
        aria-labelledby="minimal-card-title"
      >
        <h2 id="minimal-card-title">Minimal card</h2>
        <article aria-label="Minimal card" class="card-minimal-state card">
          No optional sections are required.
        </article>
      </section>

      <section
        class="component-state-section"
        aria-labelledby="compact-card-title"
      >
        <h2 id="compact-card-title">Compact card</h2>
        <article size="sm" aria-label="Compact card" class="card">
          <header>
            <h2>Storage</h2>
          </header>
          <footer>8.4 GB available</footer>
        </article>
      </section>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Semantic content composition.

Anatomy

Root styling selector

  • .card

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

AttributeAccessPurpose
sizeAuthoredUse sm for compact spacing; omit for the default size.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

VariablePurpose
--card-padding-blockBlock padding; defaults to four spacing units, or three for size=sm.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Semantic content composition. AngularCSS supplies styling without a runtime directive. Native HTML owns platform behavior; AngularTS owns application values, commands, and authored state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Prefer semantic landmarks and native elements inside the layout. Any interactive handles or triggers must retain an accessible name and visible focus indicator.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

9 - chart

HTML-first chart container, legend, axis, and tooltip primitives

Use Chart to frame application-rendered HTML, SVG, canvas, or a locally bundled chart library with a consistent container, axis, legend, and tooltip contract. For simple authored HTML plots, data-value and data-color synchronize to --value and --chart-color.

<figure aria-label="Monthly visitors" class="chart">
  <section>
    <hr />
    <ul>
      <li>
        <span
          aria-label="January desktop"
          data-value="72%"
          data-color="var(--chart-1)"
        ></span>
      </li>
    </ul>
  </section>
  <footer><span>Jan</span></footer>
</figure>

AngularCSS does not implement a chart engine. Plotting, scales, data, formatting, hover selection, and active-series state remain with authored HTML, the application’s selected chart library, and AngularTS. This keeps Chart from covering AngularTS application behavior while providing stable semantic and customization hooks.

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Chart</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="chart-example">
    <figure
      class="visual-example chart"
      aria-label="Desktop and mobile visitors from January through June"
    >
      <section>
        <ul>
          <li>
            <span
              role="img"
              aria-label="January desktop"
              data-value="61%"
              data-color="#2563eb"
              style="--value: 61%; --chart-color: #2563eb"
            ></span>
            <span
              role="img"
              aria-label="January mobile"
              data-value="26%"
              data-color="#60a5fa"
              style="--value: 26%; --chart-color: #60a5fa"
            ></span>
          </li>
          <li>
            <span
              role="img"
              aria-label="February desktop"
              data-value="100%"
              data-color="#2563eb"
              style="--value: 100%; --chart-color: #2563eb"
            ></span>
            <span
              role="img"
              aria-label="February mobile"
              data-value="66%"
              data-color="#60a5fa"
              style="--value: 66%; --chart-color: #60a5fa"
            ></span>
          </li>
          <li>
            <span
              role="img"
              aria-label="March desktop"
              data-value="78%"
              data-color="#2563eb"
              style="--value: 78%; --chart-color: #2563eb"
            ></span>
            <span
              role="img"
              aria-label="March mobile"
              data-value="39%"
              data-color="#60a5fa"
              style="--value: 39%; --chart-color: #60a5fa"
            ></span>
          </li>
          <li>
            <span
              role="img"
              aria-label="April desktop"
              data-value="24%"
              data-color="#2563eb"
              style="--value: 24%; --chart-color: #2563eb"
            ></span>
            <span
              role="img"
              aria-label="April mobile"
              data-value="62%"
              data-color="#60a5fa"
              style="--value: 62%; --chart-color: #60a5fa"
            ></span>
          </li>
          <li>
            <span
              role="img"
              aria-label="May desktop"
              data-value="69%"
              data-color="#2563eb"
              style="--value: 69%; --chart-color: #2563eb"
            ></span>
            <span
              role="img"
              aria-label="May mobile"
              data-value="43%"
              data-color="#60a5fa"
              style="--value: 43%; --chart-color: #60a5fa"
            ></span>
          </li>
          <li>
            <span
              role="img"
              aria-label="June desktop"
              data-value="70%"
              data-color="#2563eb"
              style="--value: 70%; --chart-color: #2563eb"
            ></span>
            <span
              role="img"
              aria-label="June mobile"
              data-value="46%"
              data-color="#60a5fa"
              style="--value: 46%; --chart-color: #60a5fa"
            ></span>
          </li>
        </ul>
      </section>
    </figure>
  </body>
</html>

Axis, grid, tooltip, and legend

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Chart Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="chartData=[{month:'January',short:'Jan',desktop:186,mobile:80,d:'61%',m:'26%'},{month:'February',short:'Feb',desktop:305,mobile:200,d:'100%',m:'66%'},{month:'March',short:'Mar',desktop:237,mobile:120,d:'78%',m:'39%'},{month:'April',short:'Apr',desktop:73,mobile:190,d:'24%',m:'62%'},{month:'May',short:'May',desktop:209,mobile:130,d:'69%',m:'43%'},{month:'June',short:'Jun',desktop:214,mobile:140,d:'70%',m:'46%'}]; tooltip={visible:false}; legendTip={visible:false}"
    data-example="chart-example-grid chart-example-axis chart-example-tooltip chart-example-legend"
  >
    <main class="chart-workflow-grid" aria-label="Chart composition workflows">
      <section class="chart-workflow" aria-labelledby="chart-grid-heading">
        <h2 id="chart-grid-heading">Grid</h2>
        <figure
          class="chart-reference-demo chart"
          aria-label="Visitor chart with horizontal grid"
        >
          <section>
            <hr />
            <ul>
              <li ng-repeat="point in chartData">
                <span
                  role="img"
                  aria-label="{{ point.month }} desktop"
                  data-value="{{ point.d }}"
                  data-color="#2563eb"
                  style="--value: {{ point.d }}; --chart-color: #2563eb"
                ></span>
                <span
                  role="img"
                  aria-label="{{ point.month }} mobile"
                  data-value="{{ point.m }}"
                  data-color="#60a5fa"
                  style="--value: {{ point.m }}; --chart-color: #60a5fa"
                ></span>
              </li>
            </ul>
          </section>
        </figure>
      </section>

      <section class="chart-workflow" aria-labelledby="chart-axis-heading">
        <h2 id="chart-axis-heading">Axis</h2>
        <figure
          class="chart-reference-demo chart"
          aria-label="Visitor chart with horizontal axis"
        >
          <section>
            <hr />
            <ul>
              <li ng-repeat="point in chartData">
                <span
                  role="img"
                  aria-label="{{ point.month }} desktop"
                  data-value="{{ point.d }}"
                  data-color="#2563eb"
                  style="--value: {{ point.d }}; --chart-color: #2563eb"
                ></span>
                <span
                  role="img"
                  aria-label="{{ point.month }} mobile"
                  data-value="{{ point.m }}"
                  data-color="#60a5fa"
                  style="--value: {{ point.m }}; --chart-color: #60a5fa"
                ></span>
              </li>
            </ul>
          </section>
          <footer>
            <span ng-repeat="point in chartData"> {{ point.short }} </span>
          </footer>
        </figure>
      </section>

      <section class="chart-workflow" aria-labelledby="chart-tooltip-heading">
        <h2 id="chart-tooltip-heading">Tooltip</h2>
        <figure
          class="chart-reference-demo chart"
          aria-label="Visitor chart with tooltip"
        >
          <section>
            <hr />
            <ul>
              <li
                ng-repeat="point in chartData"
                ng-mouseenter="tooltip.visible=true;tooltip.month=point.month;tooltip.desktop=point.desktop;tooltip.mobile=point.mobile"
                ng-mouseleave="tooltip.visible=false"
              >
                <span
                  role="img"
                  aria-label="{{ point.month }} desktop"
                  data-value="{{ point.d }}"
                  data-color="#2563eb"
                  style="--value: {{ point.d }}; --chart-color: #2563eb"
                ></span>
                <span
                  role="img"
                  aria-label="{{ point.month }} mobile"
                  data-value="{{ point.m }}"
                  data-color="#60a5fa"
                  style="--value: {{ point.m }}; --chart-color: #60a5fa"
                ></span>
              </li>
            </ul>
            <output class="chart-floating-tooltip" ng-if="tooltip.visible">
              <strong>{{ tooltip.month }}</strong>
              <dl>
                <div>
                  <dt>
                    <span
                      aria-hidden="true"
                      data-color="#2563eb"
                      style="--chart-color: #2563eb"
                    ></span
                    >Desktop
                  </dt>
                  <dd>{{ tooltip.desktop }}</dd>
                </div>
                <div>
                  <dt>
                    <span
                      aria-hidden="true"
                      data-color="#60a5fa"
                      style="--chart-color: #60a5fa"
                    ></span
                    >Mobile
                  </dt>
                  <dd>{{ tooltip.mobile }}</dd>
                </div>
              </dl>
            </output>
          </section>
          <footer>
            <span ng-repeat="point in chartData"> {{ point.short }} </span>
          </footer>
        </figure>
      </section>

      <section class="chart-workflow" aria-labelledby="chart-legend-heading">
        <h2 id="chart-legend-heading">Legend</h2>
        <figure
          class="chart-reference-demo chart"
          aria-label="Visitor chart with legend and tooltip"
        >
          <section>
            <hr />
            <ul>
              <li
                ng-repeat="point in chartData"
                ng-mouseenter="legendTip.visible=true;legendTip.month=point.month;legendTip.desktop=point.desktop;legendTip.mobile=point.mobile"
                ng-mouseleave="legendTip.visible=false"
              >
                <span
                  role="img"
                  aria-label="{{ point.month }} desktop"
                  data-value="{{ point.d }}"
                  data-color="#2563eb"
                  style="--value: {{ point.d }}; --chart-color: #2563eb"
                ></span>
                <span
                  role="img"
                  aria-label="{{ point.month }} mobile"
                  data-value="{{ point.m }}"
                  data-color="#60a5fa"
                  style="--value: {{ point.m }}; --chart-color: #60a5fa"
                ></span>
              </li>
            </ul>
            <output class="chart-floating-tooltip" ng-if="legendTip.visible">
              <strong>{{ legendTip.month }}</strong>
              <dl>
                <div>
                  <dt>
                    <span
                      aria-hidden="true"
                      data-color="#2563eb"
                      style="--chart-color: #2563eb"
                    ></span
                    >Desktop
                  </dt>
                  <dd>{{ legendTip.desktop }}</dd>
                </div>
                <div>
                  <dt>
                    <span
                      aria-hidden="true"
                      data-color="#60a5fa"
                      style="--chart-color: #60a5fa"
                    ></span
                    >Mobile
                  </dt>
                  <dd>{{ legendTip.mobile }}</dd>
                </div>
              </dl>
            </output>
          </section>
          <footer>
            <span ng-repeat="point in chartData"> {{ point.short }} </span>
          </footer>
          <ul>
            <li>
              <span data-color="#2563eb" style="--chart-color: #2563eb"></span
              >Desktop
            </li>
            <li>
              <span data-color="#60a5fa" style="--chart-color: #60a5fa"></span
              >Mobile
            </li>
          </ul>
        </figure>
      </section>
    </main>
  </body>
</html>

Interactive, RTL, and tooltip variants

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Chart Compositions</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="activeChart='desktop'; demoTip={visible:false}; rtlTip={visible:false}; interactiveData=[{date:'Apr 1',d:222,m:150,dp:'49%',mp:'36%'},{date:'Apr 2',d:97,m:180,dp:'21%',mp:'43%'},{date:'Apr 3',d:167,m:120,dp:'37%',mp:'29%'},{date:'Apr 4',d:242,m:260,dp:'53%',mp:'62%'},{date:'Apr 5',d:373,m:290,dp:'82%',mp:'69%'},{date:'Apr 6',d:301,m:340,dp:'66%',mp:'81%'},{date:'Apr 7',d:245,m:180,dp:'54%',mp:'43%'},{date:'Apr 8',d:409,m:320,dp:'90%',mp:'76%'},{date:'Apr 9',d:59,m:110,dp:'13%',mp:'26%'},{date:'Apr 10',d:261,m:190,dp:'57%',mp:'45%'},{date:'Apr 11',d:327,m:350,dp:'72%',mp:'83%'},{date:'Apr 12',d:292,m:210,dp:'64%',mp:'50%'},{date:'Apr 13',d:342,m:380,dp:'75%',mp:'90%'},{date:'Apr 14',d:137,m:220,dp:'30%',mp:'52%'},{date:'Apr 15',d:120,m:170,dp:'26%',mp:'40%'},{date:'Apr 16',d:138,m:190,dp:'30%',mp:'45%'},{date:'Apr 17',d:446,m:360,dp:'98%',mp:'86%'},{date:'Apr 18',d:364,m:410,dp:'80%',mp:'98%'},{date:'Apr 19',d:243,m:180,dp:'54%',mp:'43%'},{date:'Apr 20',d:89,m:150,dp:'20%',mp:'36%'},{date:'Apr 21',d:137,m:200,dp:'30%',mp:'48%'},{date:'Apr 22',d:224,m:170,dp:'49%',mp:'40%'},{date:'Apr 23',d:138,m:230,dp:'30%',mp:'55%'},{date:'Apr 24',d:387,m:290,dp:'85%',mp:'69%'},{date:'Apr 25',d:215,m:250,dp:'47%',mp:'60%'},{date:'Apr 26',d:75,m:130,dp:'17%',mp:'31%'},{date:'Apr 27',d:383,m:420,dp:'84%',mp:'100%'},{date:'Apr 28',d:122,m:180,dp:'27%',mp:'43%'},{date:'Apr 29',d:315,m:240,dp:'69%',mp:'57%'},{date:'Apr 30',d:454,m:380,dp:'100%',mp:'90%'}]; rtlData=[{month:'يناير',short:'ينا',desktop:186,mobile:80,d:'61%',m:'26%'},{month:'فبراير',short:'فبر',desktop:305,mobile:200,d:'100%',m:'66%'},{month:'مارس',short:'مار',desktop:237,mobile:120,d:'78%',m:'39%'},{month:'أبريل',short:'أبر',desktop:73,mobile:190,d:'24%',m:'62%'},{month:'مايو',short:'ماي',desktop:209,mobile:130,d:'69%',m:'43%'},{month:'يونيو',short:'يون',desktop:214,mobile:140,d:'70%',m:'46%'}]"
    data-example="chart-demo chart-rtl chart-tooltip"
  >
    <main
      class="chart-composition-grid"
      aria-label="Chart reference compositions"
    >
      <article class="chart-interactive-card chart-composition-wide card">
        <header class="chart-interactive-header">
          <div class="chart-interactive-copy">
            <h2>Bar Chart - Interactive</h2>
            <p>Showing total visitors for the last 3 months</p>
          </div>
          <div class="chart-series-controls" aria-label="Visitor series">
            <button
              type="button"
              variant="ghost"
              aria-pressed="{{ activeChart == 'desktop' }}"
              ng-click="activeChart='desktop'"
            >
              <span>Desktop</span><strong>7,324</strong>
            </button>
            <button
              type="button"
              variant="ghost"
              aria-pressed="{{ activeChart == 'mobile' }}"
              ng-click="activeChart='mobile'"
            >
              <span>Mobile</span><strong>7,250</strong>
            </button>
          </div>
        </header>
        <section class="chart-interactive-content">
          <figure
            class="chart-interactive-demo chart"
            aria-label="Interactive daily visitors"
          >
            <section>
              <hr />
              <div class="chart-daily-bars">
                <span
                  role="img"
                  ng-repeat="point in interactiveData"
                  aria-label="{{ point.date }} {{ activeChart }}"
                  data-value="{{ activeChart == 'desktop' ? point.dp : point.mp }}"
                  data-color="{{ activeChart == 'desktop' ? 'var(--chart-2)' : 'var(--chart-1)' }}"
                  ng-mouseenter="demoTip.visible=true;demoTip.date=point.date;demoTip.value=activeChart == 'desktop' ? point.d : point.m"
                  ng-mouseleave="demoTip.visible=false"
                  style="--value: {{ activeChart == 'desktop' ? point.dp : point.mp }}; --chart-color: {{ activeChart == 'desktop' ? 'var(--chart-2)' : 'var(--chart-1)' }}"
                ></span>
              </div>
              <output class="chart-floating-tooltip" ng-if="demoTip.visible">
                <strong>{{ demoTip.date }}, 2024</strong>
                <dl>
                  <div>
                    <dt>
                      <span
                        aria-hidden="true"
                        data-color="{{ activeChart == 'desktop' ? 'var(--chart-2)' : 'var(--chart-1)' }}"
                        style="--chart-color: {{ activeChart == 'desktop' ? 'var(--chart-2)' : 'var(--chart-1)' }}"
                      ></span>
                      {{ activeChart == 'desktop' ? 'Desktop' : 'Mobile' }}
                    </dt>
                    <dd>{{ demoTip.value }}</dd>
                  </div>
                </dl>
              </output>
            </section>
            <footer class="chart-date-axis">
              <span>Apr 1</span>
              <span>Apr 8</span>
              <span>Apr 15</span>
              <span>Apr 22</span>
              <span>Apr 30</span>
            </footer>
          </figure>
        </section>
      </article>

      <section
        class="chart-composition"
        aria-labelledby="chart-rtl-heading"
        dir="rtl"
        lang="ar"
      >
        <h2 id="chart-rtl-heading">مخطط من اليمين إلى اليسار</h2>
        <figure
          class="chart-reference-demo chart"
          aria-label="زوار سطح المكتب والجوال"
        >
          <section>
            <hr />
            <ul>
              <li
                ng-repeat="point in rtlData"
                ng-mouseenter="rtlTip.visible=true;rtlTip.month=point.month;rtlTip.desktop=point.desktop;rtlTip.mobile=point.mobile"
                ng-mouseleave="rtlTip.visible=false"
              >
                <span
                  role="img"
                  aria-label="{{ point.month }} سطح المكتب"
                  data-value="{{ point.d }}"
                  data-color="var(--chart-2)"
                  style="--value: {{ point.d }}; --chart-color: var(--chart-2)"
                ></span>
                <span
                  role="img"
                  aria-label="{{ point.month }} الجوال"
                  data-value="{{ point.m }}"
                  data-color="var(--chart-1)"
                  style="--value: {{ point.m }}; --chart-color: var(--chart-1)"
                ></span>
              </li>
            </ul>
            <output class="chart-floating-tooltip" ng-if="rtlTip.visible">
              <strong>{{ rtlTip.month }}</strong>
              <dl>
                <div>
                  <dt>
                    <span
                      aria-hidden="true"
                      data-color="var(--chart-2)"
                      style="--chart-color: var(--chart-2)"
                    ></span
                    >سطح المكتب
                  </dt>
                  <dd>{{ rtlTip.desktop }}</dd>
                </div>
                <div>
                  <dt>
                    <span
                      aria-hidden="true"
                      data-color="var(--chart-1)"
                      style="--chart-color: var(--chart-1)"
                    ></span
                    >الجوال
                  </dt>
                  <dd>{{ rtlTip.mobile }}</dd>
                </div>
              </dl>
            </output>
          </section>
          <footer>
            <span ng-repeat="point in rtlData"> {{ point.short }} </span>
          </footer>
          <ul>
            <li>
              <span
                data-color="var(--chart-2)"
                style="--chart-color: var(--chart-2)"
              ></span
              >سطح المكتب
            </li>
            <li>
              <span
                data-color="var(--chart-1)"
                style="--chart-color: var(--chart-1)"
              ></span
              >الجوال
            </li>
          </ul>
        </figure>
      </section>

      <section
        class="chart-composition"
        aria-labelledby="chart-tooltip-gallery-heading"
      >
        <h2 id="chart-tooltip-gallery-heading">Tooltip anatomy</h2>
        <figure
          class="chart-tooltip-gallery chart"
          aria-label="Chart tooltip anatomy examples"
        >
          <output>
            <strong>Page Views</strong>
            <dl>
              <div>
                <dt>
                  <span
                    aria-hidden="true"
                    data-color="var(--chart-1)"
                    style="--chart-color: var(--chart-1)"
                  ></span
                  >Desktop
                </dt>
                <dd>186</dd>
              </div>
              <div>
                <dt>
                  <span
                    aria-hidden="true"
                    data-color="var(--chart-2)"
                    style="--chart-color: var(--chart-2)"
                  ></span
                  >Mobile
                </dt>
                <dd>80</dd>
              </div>
            </dl>
          </output>
          <output>
            <dl>
              <div>
                <dt>
                  <span
                    aria-hidden="true"
                    indicator="dashed"
                    data-color="var(--chart-3)"
                    style="--chart-color: var(--chart-3)"
                  ></span
                  >Chrome
                </dt>
                <dd>1,286</dd>
              </div>
              <div>
                <dt>
                  <span
                    aria-hidden="true"
                    indicator="dashed"
                    data-color="var(--chart-4)"
                    style="--chart-color: var(--chart-4)"
                  ></span
                  >Firefox
                </dt>
                <dd>1,000</dd>
              </div>
            </dl>
          </output>
          <output>
            <dl>
              <div>
                <dt>
                  <span
                    aria-hidden="true"
                    indicator="line"
                    data-color="var(--chart-3)"
                    style="--chart-color: var(--chart-3)"
                  ></span
                  ><strong>Page Views</strong><br />Desktop
                </dt>
                <dd>12,486</dd>
              </div>
            </dl>
          </output>
          <output>
            <dl>
              <div>
                <dt>
                  <span
                    aria-hidden="true"
                    data-color="var(--chart-1)"
                    style="--chart-color: var(--chart-1)"
                  ></span
                  >Chrome
                </dt>
                <dd>1,286</dd>
              </div>
            </dl>
          </output>
        </figure>
      </section>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Authored figures, tables, and CSS variables.

Anatomy

Root styling selector

  • .chart

Semantic structure

Apply .chart to an accessible figure. Compose its optional title, plot, grid, grouped bars, axis, legend, and tooltip from semantic header, section, hr, ul, li, footer, output, and description-list elements; no anatomy classes are required.

API

Attributes and state

AttributeAccessPurpose
data-colorAuthoredSeries color key used by the example or application to set --chart-color.
data-valueAuthoredAuthored bar height as a percentage when --value is not set.
indicatorAuthoredLegend indicator: line or dashed; omit for a solid mark.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

VariablePurpose
--chart-colorColor for an authored series, mark, or legend indicator.
--valueBar height as a percentage; falls back to data-value and then 50%.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Semantic figure, heading, list, and data markup owns chart meaning. CSS variables provide visual values and colors; authored HTML, SVG, canvas, or an application-selected chart library owns plotting, scales, data, formatting, and interaction. AngularCSS registers no chart directive.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Give every chart root a useful accessible name and provide a textual or tabular equivalent when exact values matter. Bars expose authored labels and values; axes and legends are lists; grid decoration is hidden; visible tooltips are status regions. Never use color as the only distinction between series.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

10 - description-list

Semantic record details

Use a native description list for stable record labels and values. AngularCSS adds responsive row presentation without changing the relationship between terms and descriptions.

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Description List</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="description-list-demo">
    <dl class="visual-example" aria-label="Account details">
      <div>
        <dt>Account owner</dt>
        <dd>Ada Lovelace</dd>
      </div>
      <div>
        <dt>Email</dt>
        <dd>ada@example.com</dd>
      </div>
      <div>
        <dt>Plan</dt>
        <dd>Enterprise</dd>
      </div>
      <div>
        <dt>Last updated</dt>
        <dd><time datetime="2026-09-05">5 September 2026</time></dd>
      </div>
    </dl>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Native description-list structure for record details.

Anatomy

Root styling selector

  • dl:has(> div > dt):has(> div > dd)

Semantic structure

Use a native dl and wrap each related dt and dd group in a direct div so rows adapt without any component or part classes.

API

Attributes and state

AttributeAccessPurpose
orientationAuthoredRow layout: horizontal or vertical; omit to become vertical on narrow viewports.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Description List styles native terms and descriptions for record details. The application owns values, formatting, redaction, and conditional rendering.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use native dl, dt, and dd elements. Group each term and its descriptions in a div when row styling is needed, and keep sensitive values subject to application authorization.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

11 - disclosure

HTML-first disclosure state and trigger/panel relationships

Native details and summary own click, keyboard, focus, and disclosure state. AngularCSS only styles the authored structure. AngularTS may observe native events when the application needs the state.

<details class="disclosure">
  <summary>Order details</summary>
  <div>Shipping address and item details.</div>
</details>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Disclosure</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="disclosure-demo">
    <details class="disclosure visual-example">
      <summary>
        <header>
          <h2>Order #4189</h2>
          <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
            <path d="m7 15 5 5 5-5M7 9l5-5 5 5" />
          </svg>
          <span class="visually-hidden">Toggle details</span>
        </header>
        <p><span>Status</span><strong>Shipped</strong></p>
      </summary>
      <section>
        <article>
          <p><strong>Shipping address</strong></p>
          <p>100 Market St, San Francisco</p>
        </article>
        <article>
          <p><strong>Items</strong></p>
          <p>2x Studio Headphones</p>
        </article>
      </section>
    </details>
  </body>
</html>

Basic, settings, and RTL

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Disclosure Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    data-example="disclosure-basic disclosure-rtl disclosure-settings"
  >
    <main class="disclosure-workflow-grid" aria-label="Disclosure workflows">
      <section
        class="disclosure-workflow"
        aria-labelledby="disclosure-basic-heading"
      >
        <h2 id="disclosure-basic-heading">Basic</h2>
        <div class="disclosure-basic-card card">
          <section>
            <details class="disclosure disclosure-product">
              <summary>
                <span>Product details</span>
                <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                  <path d="m6 9 6 6 6-6" />
                </svg>
              </summary>
              <div>
                <p>
                  This panel can be expanded or collapsed to reveal additional
                  content.
                </p>
                <button size="xs">Learn More</button>
              </div>
            </details>
          </section>
        </div>
      </section>

      <section
        class="disclosure-workflow"
        aria-labelledby="disclosure-settings-heading"
      >
        <h2 id="disclosure-settings-heading">Settings</h2>
        <div size="sm" class="disclosure-settings-card card">
          <header>
            <h2>Radius</h2>
            <p>Set the corner radius of the element.</p>
          </header>
          <section>
            <section class="disclosure-settings">
              <div class="disclosure-settings-fields">
                <label class="visually-hidden" for="radius-x">Radius X</label>
                <input id="radius-x" type="number" value="0" />
                <label class="visually-hidden" for="radius-y">Radius Y</label>
                <input id="radius-y" type="number" value="0" />
                <details class="disclosure disclosure-settings-disclosure">
                  <summary aria-label="Toggle additional radius settings">
                    <svg
                      class="disclosure-maximize"
                      viewBox="0 0 24 24"
                      fill="none"
                      aria-hidden="true"
                    >
                      <path
                        d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3M3 16v3a2 2 0 0 0 2 2h3m8 0h3a2 2 0 0 0 2-2v-3"
                      />
                    </svg>
                    <svg
                      class="disclosure-minimize"
                      viewBox="0 0 24 24"
                      fill="none"
                      aria-hidden="true"
                    >
                      <path
                        d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3M3 16h3a2 2 0 0 1 2 2v3m8 0v-3a2 2 0 0 1 2-2h3"
                      />
                    </svg>
                  </summary>
                  <div class="disclosure-settings-more">
                    <label class="visually-hidden" for="radius-bottom-x"
                      >Bottom radius X</label
                    >
                    <input id="radius-bottom-x" type="number" value="0" />
                    <label class="visually-hidden" for="radius-bottom-y"
                      >Bottom radius Y</label
                    >
                    <input id="radius-bottom-y" type="number" value="0" />
                  </div>
                </details>
              </div>
            </section>
          </section>
        </div>
      </section>

      <section
        class="disclosure-workflow disclosure-workflow-wide"
        aria-labelledby="disclosure-rtl-heading"
        dir="rtl"
        lang="ar"
      >
        <h2 id="disclosure-rtl-heading">من اليمين إلى اليسار</h2>
        <details class="disclosure">
          <summary>
            <header>
              <h4>الطلب #4189</h4>
              <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                <path d="m7 15 5 5 5-5M7 9l5-5 5 5" />
              </svg>
              <span class="visually-hidden">تبديل التفاصيل</span>
            </header>
            <p><span>الحالة</span><strong>تم الشحن</strong></p>
          </summary>
          <section>
            <article>
              <p><strong>عنوان الشحن</strong></p>
              <p>100 Market St, San Francisco</p>
            </article>
            <article>
              <p><strong>العناصر</strong></p>
              <p>2x سماعات الاستوديو</p>
            </article>
          </section>
        </details>
      </section>
    </main>
  </body>
</html>

File tree

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Disclosure Compositions</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="disclosure-file-tree">
    <main aria-label="Disclosure file tree composition">
      <div size="sm" class="disclosure-file-card visual-example card">
        <header>
          <section ng-tabs>
            <menu aria-label="File views">
              <button aria-selected="true">Explorer</button>
              <button>Outline</button>
            </menu>
            <section>
              <span class="visually-hidden">Explorer file tree</span>
            </section>
            <section>
              <span class="visually-hidden">No outline available</span>
            </section>
          </section>
        </header>
        <section>
          <div class="disclosure-file-tree">
            <details class="disclosure">
              <summary>
                <svg
                  class="tree-chevron"
                  viewBox="0 0 24 24"
                  fill="none"
                  aria-hidden="true"
                >
                  <path d="m9 18 6-6-6-6" /></svg
                ><svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                  <path
                    d="M4 19V5a2 2 0 0 1 2-2h5l2 3h5a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2Z"
                  /></svg
                ><span>components</span>
              </summary>
              <div>
                <details class="disclosure">
                  <summary>
                    <svg
                      class="tree-chevron"
                      viewBox="0 0 24 24"
                      fill="none"
                      aria-hidden="true"
                    >
                      <path d="m9 18 6-6-6-6" /></svg
                    ><svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                      <path
                        d="M4 19V5a2 2 0 0 1 2-2h5l2 3h5a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2Z"
                      /></svg
                    ><span>ui</span>
                  </summary>
                  <div>
                    <button variant="link" size="sm">
                      <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                        <path
                          d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"
                        />
                        <path d="M14 2v6h6" /></svg
                      >button.tsx
                    </button>
                    <button variant="link" size="sm">
                      <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                        <path
                          d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"
                        />
                        <path d="M14 2v6h6" /></svg
                      >card.tsx
                    </button>
                    <button variant="link" size="sm">
                      <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                        <path
                          d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"
                        />
                        <path d="M14 2v6h6" /></svg
                      >dialog.tsx
                    </button>
                    <button variant="link" size="sm">
                      <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                        <path
                          d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"
                        />
                        <path d="M14 2v6h6" /></svg
                      >input.tsx
                    </button>
                    <button variant="link" size="sm">
                      <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                        <path
                          d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"
                        />
                        <path d="M14 2v6h6" /></svg
                      >select.tsx
                    </button>
                    <button variant="link" size="sm">
                      <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                        <path
                          d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"
                        />
                        <path d="M14 2v6h6" /></svg
                      >table.tsx
                    </button>
                  </div>
                </details>
                <button variant="link" size="sm">
                  <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                    <path
                      d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"
                    />
                    <path d="M14 2v6h6" /></svg
                  >login-form.tsx
                </button>
                <button variant="link" size="sm">
                  <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                    <path
                      d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"
                    />
                    <path d="M14 2v6h6" /></svg
                  >register-form.tsx
                </button>
              </div>
            </details>
            <details class="disclosure">
              <summary>
                <svg
                  class="tree-chevron"
                  viewBox="0 0 24 24"
                  fill="none"
                  aria-hidden="true"
                >
                  <path d="m9 18 6-6-6-6" /></svg
                ><svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                  <path
                    d="M4 19V5a2 2 0 0 1 2-2h5l2 3h5a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2Z"
                  /></svg
                ><span>lib</span>
              </summary>
              <div>
                <button variant="link" size="sm">utils.ts</button
                ><button variant="link" size="sm">cn.ts</button
                ><button variant="link" size="sm">api.ts</button>
              </div>
            </details>
            <details class="disclosure">
              <summary>
                <svg
                  class="tree-chevron"
                  viewBox="0 0 24 24"
                  fill="none"
                  aria-hidden="true"
                >
                  <path d="m9 18 6-6-6-6" /></svg
                ><svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                  <path
                    d="M4 19V5a2 2 0 0 1 2-2h5l2 3h5a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2Z"
                  /></svg
                ><span>hooks</span>
              </summary>
              <div>
                <button variant="link" size="sm">use-media-query.ts</button
                ><button variant="link" size="sm">use-debounce.ts</button
                ><button variant="link" size="sm">use-local-storage.ts</button>
              </div>
            </details>
            <details class="disclosure">
              <summary>
                <svg
                  class="tree-chevron"
                  viewBox="0 0 24 24"
                  fill="none"
                  aria-hidden="true"
                >
                  <path d="m9 18 6-6-6-6" /></svg
                ><svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                  <path
                    d="M4 19V5a2 2 0 0 1 2-2h5l2 3h5a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2Z"
                  /></svg
                ><span>types</span>
              </summary>
              <div>
                <button variant="link" size="sm">index.d.ts</button
                ><button variant="link" size="sm">api.d.ts</button>
              </div>
            </details>
            <details class="disclosure">
              <summary>
                <svg
                  class="tree-chevron"
                  viewBox="0 0 24 24"
                  fill="none"
                  aria-hidden="true"
                >
                  <path d="m9 18 6-6-6-6" /></svg
                ><svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
                  <path
                    d="M4 19V5a2 2 0 0 1 2-2h5l2 3h5a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2Z"
                  /></svg
                ><span>public</span>
              </summary>
              <div>
                <button variant="link" size="sm">favicon.ico</button
                ><button variant="link" size="sm">logo.svg</button
                ><button variant="link" size="sm">images</button>
              </div>
            </details>
            <button variant="link" size="sm">app.tsx</button>
            <button variant="link" size="sm">layout.tsx</button>
            <button variant="link" size="sm">globals.css</button>
            <button variant="link" size="sm">package.json</button>
            <button variant="link" size="sm">tsconfig.json</button>
            <button variant="link" size="sm">README.md</button>
            <button variant="link" size="sm">.gitignore</button>
          </div>
        </section>
      </div>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Native details and summary disclosure.

Anatomy

Root styling selector

  • .disclosure

Semantic structure

Apply .disclosure to a native details element with a direct summary followed by authored content. No nested AngularCSS attributes are required.

API

Attributes and state

AttributeAccessPurpose
openAuthoredInitial or controlled open state.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Native details and summary own disclosure, focus, and keyboard behavior. Use open for initial state and AngularTS only when application state must observe or control the native element. AngularCSS registers no disclosure directive.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use a direct summary as the accessible trigger. The browser exposes disclosure state and provides Enter and Space activation without authored roles or ARIA state.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

12 - empty

Empty state layout

Empty states compose media, title, description, and action content parts.

<section class="empty">
  <header>
    <figure variant="icon"></figure>
    <h2>No projects yet</h2>
    <p>Create your first project.</p>
  </header>
</section>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Empty</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="empty-demo">
    <section class="visual-example empty" aria-live="polite">
      <header>
        <figure variant="icon">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            stroke-width="1.75"
            stroke="currentColor"
          >
            <path
              stroke-linecap="round"
              stroke-linejoin="round"
              d="M3.75 9.75h16.5m-13.5 0V6.75A2.25 2.25 0 0 1 9 4.5h6a2.25 2.25 0 0 1 2.25 2.25v3m-12 0 1.2 8.4A2.25 2.25 0 0 0 8.68 20.25h6.64a2.25 2.25 0 0 0 2.23-2.1l1.2-8.4"
            />
          </svg>
        </figure>
        <h2>No Projects Yet</h2>
        <p>
          You haven't created any projects yet. Get started by creating your
          first project.
        </p>
      </header>
      <section>
        <div class="row">
          <button>Create Project</button>
          <button variant="outline">Import Project</button>
        </div>
      </section>
      <a class="empty-learn-more" href="#learn-more">
        Learn More
        <svg viewBox="0 0 24 24" fill="none" aria-hidden="true">
          <path
            d="M7 17 17 7M7 7h10v10"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
          />
        </svg>
      </a>
    </section>
  </body>
</html>

Workflows

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Empty Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="emptyQuery='';emptyAction='Ready'"
  >
    <main class="empty-workflow-grid" aria-label="Empty state workflows">
      <section data-example="empty-avatar" class="empty-workflow empty">
        <header>
          <figure>
            <span class="empty-avatar-large avatar"
              ><img src="../../images/avatars/01.png" alt="Jane Doe" /><span
                >JD</span
              ></span
            >
          </figure>
          <h2>User Offline</h2>
          <p>
            This user is currently offline. Leave a message or try again later.
          </p>
        </header>
        <section>
          <button
            size="sm"
            type="button"
            ng-click="emptyAction='Message queued'"
          >
            Leave Message
          </button>
        </section>
      </section>
      <section data-example="empty-avatar-group" class="empty-workflow empty">
        <header>
          <figure class="empty-avatar-group">
            <span class="avatar"
              ><img src="../../images/avatars/01.png" alt="Jane" /></span
            ><span class="avatar"
              ><img src="../../images/avatars/02.png" alt="Alex" /></span
            ><span class="avatar"
              ><img src="../../images/avatars/03.png" alt="Sam"
            /></span>
          </figure>
          <h2>No Team Members</h2>
          <p>Invite your team to collaborate on this project.</p>
        </header>
        <section>
          <button
            size="sm"
            type="button"
            ng-click="emptyAction='Invite opened'"
          >
            + Invite Members
          </button>
        </section>
      </section>
      <section
        data-example="empty-background"
        class="empty-workflow empty-muted-demo empty"
      >
        <header>
          <figure variant="icon">!</figure>
          <h2>No Notifications</h2>
          <p>You're all caught up. New notifications will appear here.</p>
        </header>
        <section>
          <button
            variant="outline"
            type="button"
            ng-click="emptyAction='Refreshed'"
          >
            Refresh
          </button>
        </section>
      </section>
      <section
        data-example="empty-card"
        class="empty-workflow empty-card-demo empty"
      >
        <header>
          <figure variant="icon"></figure>
          <h2>No projects yet</h2>
          <p>
            You haven't created any projects yet. Create your first project.
          </p>
        </header>
        <section>
          <div class="row">
            <button type="button" ng-click="emptyAction='Create project'">
              Create project</button
            ><button
              variant="outline"
              type="button"
              ng-click="emptyAction='Import project'"
            >
              Import project
            </button>
          </div>
          <a href="#learn">Learn more</a>
        </section>
      </section>
      <section data-example="empty-input-group" class="empty-workflow empty">
        <header>
          <h2>404 - Not Found</h2>
          <p>The page you're looking for doesn't exist. Try searching below.</p>
        </header>
        <section>
          <div class="input-group">
            <input
              ng-model="emptyQuery"
              placeholder="Try searching for pages..."
              aria-label="Search missing pages"
            />
            <div></div>
            <div align="inline-end">
              <kbd>/</kbd>
            </div>
          </div>
          <p>Need help? <a href="#support">Contact support</a></p>
        </section>
      </section>
      <section
        data-example="empty-outline"
        class="empty-workflow empty-outline-demo empty"
      >
        <header>
          <figure variant="icon"></figure>
          <h2>Cloud Storage Empty</h2>
          <p>Upload files to access them anywhere.</p>
        </header>
        <section>
          <button
            variant="outline"
            size="sm"
            type="button"
            ng-click="emptyAction='Upload opened'"
          >
            Upload Files
          </button>
        </section>
      </section>
      <section
        data-example="empty-rtl"
        class="empty-workflow empty"
        dir="rtl"
        lang="ar"
      >
        <header>
          <figure variant="icon"></figure>
          <h2>لا توجد مشاريع بعد</h2>
          <p>لم تقم بإنشاء أي مشاريع بعد. ابدأ بإنشاء مشروعك الأول.</p>
        </header>
        <section>
          <div class="row">
            <button type="button" ng-click="emptyAction='إنشاء مشروع'">
              إنشاء مشروع</button
            ><button
              variant="outline"
              type="button"
              ng-click="emptyAction='استيراد مشروع'"
            >
              استيراد مشروع
            </button>
          </div>
        </section>
      </section>
      <output class="empty-workflow-output">
        {{ emptyAction }} · {{ emptyQuery }}
      </output>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Semantic empty-state content.

Anatomy

Root styling selector

  • .empty

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

AttributeAccessPurpose
variantAuthoredOptional direct figure presentation: icon; omit for the default media treatment.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Semantic empty-state content. AngularCSS supplies styling without a runtime directive. Native HTML owns platform behavior; AngularTS owns application values, commands, and authored state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Prefer semantic landmarks and native elements inside the layout. Any interactive handles or triggers must retain an accessible name and visible focus indicator.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

13 - field

Group labels, helper text, and errors with semantic field wrapper selectors.

Use the field wrapper and field parts to define standard form structure.

<div class="field">
  <label for="email">Email</label>
  <input id="email" type="email" placeholder="Email" />
  <p>Use your work email.</p>
</div>

<div class="field">
  <label for="invalid-email">Email</label>
  <input id="invalid-email" aria-invalid="true" />
  <p class="field-error">Enter a valid email.</p>
</div>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Field</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak ng-init="name='Jane Doe'; email=''">
    <form class="stack">
      <fieldset class="field-set">
        <legend>Profile</legend>
        <div class="field-group">
          <div class="field">
            <label for="demo-profile-name">Name</label>
            <input
              id="demo-profile-name"
              aria-describedby="demo-profile-name-description"
              placeholder="Jane Doe"
              ng-model="name"
            />
            <p id="demo-profile-name-description">
              Use your public display name.
            </p>
          </div>
          <div class="field">
            <label for="demo-profile-email"> Email </label>
            <input
              id="demo-profile-email"
              type="email"
              placeholder="Enter an email"
              required
              aria-describedby="demo-profile-email-error"
              ng-model="email"
            />
            <p
              id="demo-profile-email-error"
              ng-show="!email"
              class="field-error"
            >
              Enter a valid email.
            </p>
          </div>
        </div>
      </fieldset>
      <output class="output">
        Preview: <span ng-bind="name"></span>
        <span ng-bind="email ? '(' + email + ')' : '(email required)'"></span>
      </output>
    </form>
  </body>
</html>

Workflows

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Field Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="fieldState={username:'',password:'',feedback:'',department:'',hardDisks:true,externalDisks:false,cds:false,servers:false,sync:true,twoFactor:false,plan:'monthly',environment:'kubernetes',minimum:200,maximum:800,street:'',city:'',zip:'',push:true,pushTasks:false,emailTasks:false,profileName:'',message:'Ready',sameAsShipping:true,month:'',year:''}"
  >
    <main class="field-workflow-grid" aria-label="Field workflows">
      <section data-example="field-input" class="field-workflow">
        <fieldset class="field-set">
          <div class="field-group">
            <div class="field">
              <label for="field-username">Username</label
              ><input
                id="field-username"
                ng-model="fieldState.username"
                placeholder="Max Leiter"
              />
              <p>Choose a unique username for your account.</p>
            </div>
            <div class="field">
              <label for="field-password">Password</label>
              <p>Must be at least 8 characters long.</p>
              <input
                id="field-password"
                type="password"
                ng-model="fieldState.password"
                placeholder="••••••••"
              />
            </div>
          </div>
        </fieldset>
      </section>

      <section data-example="field-textarea" class="field-workflow">
        <fieldset class="field-set">
          <div class="field-group">
            <div class="field">
              <label for="field-feedback">Feedback</label
              ><textarea
                id="field-feedback"
                ng-model="fieldState.feedback"
                placeholder="Your feedback helps us improve..."
                rows="4"
              ></textarea>
              <p>Share your thoughts about our service.</p>
            </div>
          </div>
        </fieldset>
      </section>

      <section data-example="field-select" class="field-workflow">
        <div class="field">
          <label for="field-department">Department</label>
          <select id="field-department" ng-model="fieldState.department">
            <option value="">Choose department</option>
            <option>Engineering</option>
            <option>Design</option>
            <option>Marketing</option>
            <option>Sales</option>
            <option>Customer Support</option>
          </select>
          <p>Select your department or area of work.</p>
        </div>
      </section>

      <section data-example="field-checkbox" class="field-workflow">
        <div class="field-group">
          <fieldset class="field-set">
            <legend variant="label">Show these items on the desktop</legend>
            <p>Select the items you want to show on the desktop.</p>
            <div class="field-choice-list checkbox-group">
              <div orientation="horizontal" class="field">
                <input
                  id="field-hard-disks"
                  type="checkbox"
                  ng-model="fieldState.hardDisks"
                /><label for="field-hard-disks">Hard disks</label>
              </div>
              <div orientation="horizontal" class="field">
                <input
                  id="field-external-disks"
                  type="checkbox"
                  ng-model="fieldState.externalDisks"
                /><label for="field-external-disks">External disks</label>
              </div>
              <div orientation="horizontal" class="field">
                <input
                  id="field-cds"
                  type="checkbox"
                  ng-model="fieldState.cds"
                /><label for="field-cds">CDs, DVDs, and iPods</label>
              </div>
              <div orientation="horizontal" class="field">
                <input
                  id="field-servers"
                  type="checkbox"
                  ng-model="fieldState.servers"
                /><label for="field-servers">Connected servers</label>
              </div>
            </div>
          </fieldset>
          <hr />
          <div orientation="horizontal" class="field">
            <input id="field-sync" type="checkbox" ng-model="fieldState.sync" />
            <section>
              <label for="field-sync"
                >Sync Desktop &amp; Documents folders</label
              >
              <p>Access these folders from your other devices.</p>
            </section>
          </div>
        </div>
      </section>

      <section data-example="field-switch" class="field-workflow">
        <div orientation="horizontal" class="field-switch-demo field">
          <label for="field-2fa">Multi-factor authentication</label
          ><input
            role="switch"
            id="field-2fa"
            type="checkbox"
            ng-model="fieldState.twoFactor"
          />
        </div>
      </section>

      <section data-example="field-radio" class="field-workflow">
        <fieldset class="field-set field-choice-list">
          <legend variant="label">Subscription Plan</legend>
          <p>Yearly and lifetime plans offer significant savings.</p>

          <div orientation="horizontal" class="field">
            <input
              id="field-monthly"
              name="field-plan"
              type="radio"
              value="monthly"
              ng-model="fieldState.plan"
            /><label for="field-monthly">Monthly ($9.99/month)</label>
          </div>
          <div orientation="horizontal" class="field">
            <input
              id="field-yearly"
              name="field-plan"
              type="radio"
              value="yearly"
              ng-model="fieldState.plan"
            /><label for="field-yearly">Yearly ($99.99/year)</label>
          </div>
          <div orientation="horizontal" class="field">
            <input
              id="field-lifetime"
              name="field-plan"
              type="radio"
              value="lifetime"
              ng-model="fieldState.plan"
            /><label for="field-lifetime">Lifetime ($299.99)</label>
          </div>
        </fieldset>
      </section>

      <section data-example="field-slider" class="field-workflow">
        <div class="field">
          <strong>Price Range</strong>
          <p>
            Set your budget range (${{ fieldState.minimum }} - ${{
            fieldState.maximum }}).
          </p>
          <div
            ng-range-slider
            min="0"
            max="1000"
            aria-label="Price Range"
            class="field-slider-demo"
          >
            <input
              type="range"
              min="0"
              max="1000"
              step="10"
              ng-model="fieldState.minimum"
              aria-label="Minimum budget"
            /><input
              type="range"
              min="0"
              max="1000"
              step="10"
              ng-model="fieldState.maximum"
              aria-label="Maximum budget"
            />
          </div>
        </div>
      </section>

      <section data-example="field-choice-card" class="field-workflow">
        <div class="field-group">
          <fieldset class="field-set field-card-list">
            <legend variant="label">Compute Environment</legend>
            <p>Select the compute environment for your cluster.</p>

            <label for="field-kubernetes"
              ><div orientation="horizontal" class="field">
                <section>
                  <strong>Kubernetes</strong>
                  <p>Run GPU workloads on a K8s cluster.</p>
                </section>
                <input
                  id="field-kubernetes"
                  name="environment"
                  type="radio"
                  value="kubernetes"
                  ng-model="fieldState.environment"
                /></div></label
            ><label for="field-vm"
              ><div orientation="horizontal" class="field">
                <section>
                  <strong>Virtual Machine</strong>
                  <p>Access a cluster to run GPU workloads.</p>
                </section>
                <input
                  id="field-vm"
                  name="environment"
                  type="radio"
                  value="vm"
                  ng-model="fieldState.environment"
                /></div
            ></label>
          </fieldset>
        </div>
      </section>

      <section data-example="field-fieldset" class="field-workflow">
        <fieldset class="field-set">
          <legend>Address Information</legend>
          <p>We need your address to deliver your order.</p>
          <div class="field-group">
            <div class="field">
              <label for="field-street">Street Address</label
              ><input
                id="field-street"
                ng-model="fieldState.street"
                placeholder="123 Main St"
              />
            </div>
            <div class="field-two-column">
              <div class="field">
                <label for="field-city">City</label
                ><input
                  id="field-city"
                  ng-model="fieldState.city"
                  placeholder="New York"
                />
              </div>
              <div class="field">
                <label for="field-zip">Postal Code</label
                ><input
                  id="field-zip"
                  ng-model="fieldState.zip"
                  placeholder="90502"
                />
              </div>
            </div>
          </div>
        </fieldset>
      </section>

      <section data-example="field-group" class="field-workflow">
        <div class="field-group">
          <fieldset class="field-set">
            <label>Responses</label>
            <p>
              Get notified when ChatGPT responds to requests that take time.
            </p>
            <div orientation="horizontal" class="field">
              <input
                id="field-push"
                type="checkbox"
                ng-model="fieldState.push"
                disabled
              /><label for="field-push">Push notifications</label>
            </div>
          </fieldset>
          <hr />
          <fieldset class="field-set">
            <label>Tasks</label>
            <p>
              Get notified when tasks have updates.
              <a href="#tasks">Manage tasks</a>
            </p>
            <div class="field-choice-list">
              <div orientation="horizontal" class="field">
                <input
                  id="field-push-tasks"
                  type="checkbox"
                  ng-model="fieldState.pushTasks"
                /><label for="field-push-tasks">Push notifications</label>
              </div>
              <div orientation="horizontal" class="field">
                <input
                  id="field-email-tasks"
                  type="checkbox"
                  ng-model="fieldState.emailTasks"
                /><label for="field-email-tasks">Email notifications</label>
              </div>
            </div>
          </fieldset>
        </div>
      </section>

      <section
        data-example="field-responsive"
        class="field-workflow field-workflow-wide"
      >
        <form
          ng-submit="fieldState.message='Profile submitted '+fieldState.profileName"
        >
          <fieldset class="field-set">
            <legend>Profile</legend>
            <p>Fill in your profile information.</p>
            <div class="field-group">
              <div orientation="responsive" class="field">
                <section>
                  <label for="field-profile-name">Name</label>
                  <p>Provide your full name for identification</p>
                </section>
                <input
                  id="field-profile-name"
                  ng-model="fieldState.profileName"
                  placeholder="Evil Rabbit"
                  required
                />
              </div>
              <div orientation="responsive" class="field-form-actions field">
                <button type="submit">Submit</button
                ><button
                  type="button"
                  variant="outline"
                  ng-click="fieldState.message='Cancelled'"
                >
                  Cancel
                </button>
              </div>
            </div>
          </fieldset>
        </form>
      </section>

      <section
        data-example="field-demo"
        class="field-workflow field-workflow-wide"
      >
        <form ng-submit="fieldState.message='Payment submitted'">
          <div class="field-group">
            <fieldset class="field-set">
              <legend>Payment Method</legend>
              <p>All transactions are secure and encrypted</p>
              <div class="field-group">
                <div class="field">
                  <label for="field-card-name">Name on Card</label
                  ><input
                    id="field-card-name"
                    placeholder="Evil Rabbit"
                    required
                  />
                </div>
                <div class="field">
                  <label for="field-card-number">Card Number</label
                  ><input
                    id="field-card-number"
                    placeholder="1234 5678 9012 3456"
                    required
                  />
                  <p>Enter your 16-digit card number</p>
                </div>
                <div class="field-three-column">
                  <div class="field">
                    <label for="field-month">Month</label
                    ><input id="field-month" placeholder="MM" />
                  </div>
                  <div class="field">
                    <label for="field-year">Year</label
                    ><input id="field-year" placeholder="YYYY" />
                  </div>
                  <div class="field">
                    <label for="field-cvv">CVV</label
                    ><input id="field-cvv" placeholder="123" required />
                  </div>
                </div>
              </div>
            </fieldset>
            <hr />
            <fieldset class="field-set">
              <legend>Billing Address</legend>
              <p>The billing address associated with your payment method</p>
              <div orientation="horizontal" class="field">
                <input
                  id="field-same-shipping"
                  type="checkbox"
                  ng-model="fieldState.sameAsShipping"
                /><label for="field-same-shipping"
                  >Same as shipping address</label
                >
              </div>
            </fieldset>
            <fieldset class="field-set">
              <div class="field">
                <label for="field-comments">Comments</label
                ><textarea
                  id="field-comments"
                  placeholder="Add any additional comments"
                ></textarea>
              </div>
            </fieldset>
            <div orientation="horizontal" class="field-form-actions field">
              <button type="submit">Submit</button
              ><button type="button" variant="outline">Cancel</button>
            </div>
          </div>
        </form>
      </section>

      <section
        data-example="field-rtl"
        class="field-workflow field-workflow-wide"
        dir="rtl"
        lang="ar"
      >
        <form>
          <div class="field-group">
            <fieldset class="field-set">
              <legend>طريقة الدفع</legend>
              <p>جميع المعاملات آمنة ومشفرة</p>
              <div class="field-group">
                <div class="field">
                  <label for="field-card-name-rtl">الاسم على البطاقة</label
                  ><input id="field-card-name-rtl" placeholder="Evil Rabbit" />
                </div>
                <div class="field">
                  <label for="field-card-number-rtl">رقم البطاقة</label
                  ><input
                    id="field-card-number-rtl"
                    placeholder="1234 5678 9012 3456"
                  />
                  <p>أدخل رقم البطاقة المكون من 16 رقمًا</p>
                </div>
                <div class="field-three-column">
                  <div class="field">
                    <label>الشهر</label><input placeholder="ش.ش" />
                  </div>
                  <div class="field">
                    <label>السنة</label><input placeholder="YYYY" />
                  </div>
                  <div class="field">
                    <label>CVV</label><input placeholder="123" />
                  </div>
                </div>
              </div>
            </fieldset>
            <hr />
            <div orientation="horizontal" class="field">
              <input
                id="field-same-shipping-rtl"
                type="checkbox"
                checked
              /><label for="field-same-shipping-rtl">نفس عنوان الشحن</label>
            </div>
            <div class="field">
              <label for="field-comments-rtl">تعليقات</label
              ><textarea
                id="field-comments-rtl"
                placeholder="أضف أي تعليقات إضافية"
              ></textarea>
            </div>
            <div orientation="horizontal" class="field-form-actions field">
              <button type="button">إرسال</button
              ><button type="button" variant="outline">إلغاء</button>
            </div>
          </div>
        </form>
      </section>
      <output class="field-workflow-output"> {{ fieldState.message }} </output>
    </main>
  </body>
</html>

Validation States

Fields derive presentation from native validity and aria-invalid; AngularTS structural directives may insert or remove controls and descriptions.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Field State Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="state={requiredEmail:'',dynamicVisible:false}"
  >
    <form class="component-state-grid" aria-label="Field state contracts">
      <section
        class="component-state-section"
        aria-labelledby="field-messages-title"
      >
        <h2 id="field-messages-title">Messages</h2>
        <div id="message-field" class="field">
          <label for="message-control">Name</label>
          <input
            id="message-control"
            aria-describedby="message-description message-error"
          />
          <p id="message-description">Use your public display name.</p>
          <p id="message-error" class="field-error">
            The display name is already in use.
          </p>
        </div>
      </section>

      <section
        class="component-state-section"
        aria-labelledby="field-invalid-title"
      >
        <h2 id="field-invalid-title">Invalid state</h2>
        <div id="explicit-invalid-field" class="field">
          <label for="explicit-invalid-control"> Workspace </label>
          <input id="explicit-invalid-control" aria-invalid="true" />
        </div>
      </section>

      <section
        class="component-state-section"
        aria-labelledby="field-required-title"
      >
        <h2 id="field-required-title">Native validation</h2>
        <div id="required-field" class="field">
          <label for="required-email">Email</label>
          <input
            id="required-email"
            type="email"
            required
            ng-model="state.requiredEmail"
          />
        </div>
      </section>

      <section
        class="component-state-section"
        aria-labelledby="field-dynamic-title"
      >
        <h2 id="field-dynamic-title">Conditional control</h2>
        <div id="dynamic-field" class="field">
          <label for="dynamic-email">Team email</label>
          <p id="dynamic-email-description">Use the address for your team.</p>
          <input
            ng-if="state.dynamicVisible"
            id="dynamic-email"
            type="email"
            aria-describedby="dynamic-email-description"
            required
          />
        </div>
        <button
          variant="outline"
          type="button"
          ng-click="state.dynamicVisible=true"
          ng-disabled="state.dynamicVisible"
        >
          Add email field
        </button>
      </section>
    </form>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Native labels, descriptions, and validation.

Anatomy

Root styling selector

  • .field

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

AttributeAccessPurpose
aria-invalidAuthoredValidation state exposed to assistive technology and CSS.
orientationAuthoredField layout: horizontal or responsive; omit for the vertical layout.
variantAuthoredCompact label typography when authored on a fieldset legend.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Field is a styling-only semantic form composition. Native labels, validation, and aria-describedby own relationships; AngularTS forms and structural directives own model, error visibility, and submission state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Connect every control to a native label. Give descriptions and errors stable IDs and author aria-describedby on the control. Use native fieldset and legend only for actual groups of related controls.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

14 - file-upload

Native file selection and transfer status

Keep file selection native and present application-owned queue and progress state beside it. AngularTS can handle drop events and backend transfer commands without introducing a second upload model.

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS File Upload</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="file-upload-demo">
    <section class="visual-example" aria-labelledby="upload-title">
      <header>
        <h2 id="upload-title">Supporting documents</h2>
        <p>PDF, PNG, or JPG files up to 10 MB.</p>
      </header>
      <label for="supporting-files">
        <strong>Choose files or drop them here</strong>
        <span>The application validates and transfers selected files.</span>
        <input
          id="supporting-files"
          type="file"
          accept=".pdf,image/png,image/jpeg"
          multiple
        />
      </label>
      <ul aria-label="Upload queue">
        <li>
          <span>contract.pdf</span>
          <output>72%</output>
          <progress value="72" max="100">72%</progress>
        </li>
      </ul>
      <output aria-live="polite">1 file ready for processing</output>
    </section>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Native file input and authored status.

Anatomy

Root styling selector

  • section:has(> label > input[type="file"])

Semantic structure

Use a semantic section with a direct label containing a native file input. Optional direct ul, native progress, and output elements present application-owned queue and transfer state without component or part classes.

API

Attributes and state

AttributeAccessPurpose
acceptAuthoredNative accepted file types on the direct file input.
draggingAuthoredPresentational drop-target state on the root section.
multipleAuthoredAllows the direct native file input to accept several files.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

File Upload styles a native file input, authored queue, native progress, and status output. AngularTS or the application owns drag-and-drop event handling, validation, transfer, retry, cancellation, and persistence.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Keep the native file input operable and labeled. Announce queue changes with a status output, label progress, and expose validation or transfer errors as text rather than color alone.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

15 - filter-bar

Search and filter controls for data views

Use a native form to collect a data view’s search and filter values. Submit, reset, AngularTS binding, and backend queries keep their existing ownership.

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Filter Bar</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="filter-bar-demo">
    <main class="visual-example">
      <form role="search" aria-label="Filter orders">
        <fieldset>
          <legend class="visually-hidden">Order filters</legend>
          <label>
            Search
            <input type="search" name="query" placeholder="Order or customer" />
          </label>
          <label>
            Status
            <select name="status">
              <option value="">All statuses</option>
              <option>Open</option>
              <option>Complete</option>
            </select>
          </label>
        </fieldset>
        <menu>
          <button variant="outline" type="reset">Reset</button>
          <button type="submit">Apply</button>
        </menu>
      </form>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Semantic search and filter form.

Anatomy

Root styling selector

  • form[role="search"]:has(> fieldset + menu)

Semantic structure

Use role="search" on a native form with a direct fieldset followed by a direct action menu. Put labeled controls in the fieldset and submit or reset actions in the menu.

API

Attributes and state

AttributeAccessPurpose
roleAuthoredExplicit semantic role when native HTML does not provide one.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Filter Bar is a native form composition. The browser and AngularTS own control values and submission; the backend may remain authoritative for queries, result counts, and pagination.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use a native form and fieldset with accessible labels. Submit applies the query, reset restores defaults, and result changes should be announced near the results they affect.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

16 - input-group

Grouped input controls and addon content with shared focus/description wiring.

Use .input-group with one native control and optional authored addons, text, and buttons. AngularTS continues to own the model and actions.

<div class="input-group">
  <input id="search" placeholder="Search" />
  <label for="search" align="inline-start">Search</label>
  <div align="inline-end">⌘K</div>
</div>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Input Group</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak>
    <main class="stack">
      <div class="field">
        <label for="search">Search</label>
        <div class="input-group">
          <input id="search" placeholder="Search documentation..." />
          <label for="search" align="inline-start">
            <span aria-hidden="true"></span>
          </label>
        </div>
      </div>
    </main>
  </body>
</html>

Reference Workflows

These packaged examples cover default, disabled, invalid, inline, text, icon, keyboard-hint, label, Button Group, and Card compositions.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Input Group Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="query=''; message=''; copyStatus='Ready'; cardStatus=''; username='angularcss'"
    data-example="input-group-workflows"
  >
    <svg class="example-icon-definitions" aria-hidden="true">
      <defs>
        <symbol id="ig-search" viewBox="0 0 24 24">
          <circle cx="11" cy="11" r="8"></circle>
          <path d="m21 21-4.3-4.3"></path>
        </symbol>
        <symbol id="ig-mail" viewBox="0 0 24 24">
          <rect width="20" height="16" x="2" y="4" rx="2"></rect>
          <path d="m22 7-10 6L2 7"></path>
        </symbol>
        <symbol id="ig-card" viewBox="0 0 24 24">
          <rect width="20" height="14" x="2" y="5" rx="2"></rect>
          <path d="M2 10h20"></path>
        </symbol>
        <symbol id="ig-check" viewBox="0 0 24 24">
          <path d="m5 12 4 4L19 6"></path>
        </symbol>
        <symbol id="ig-eye-off" viewBox="0 0 24 24">
          <path d="m2 2 20 20"></path>
          <path
            d="M6.7 6.7C4.8 8 3.3 9.8 2.5 12c1.5 4 5.2 7 9.5 7 1.5 0 2.9-.3 4.1-.9"
          ></path>
          <path
            d="M10.7 5.1A10 10 0 0 1 12 5c4.3 0 8 3 9.5 7a10.8 10.8 0 0 1-2.1 3.4"
          ></path>
        </symbol>
        <symbol id="ig-star" viewBox="0 0 24 24">
          <path
            d="m12 2 3.1 6.3 6.9 1-5 4.9 1.2 6.8-6.2-3.2L5.8 21 7 14.2 2 9.3l6.9-1Z"
          ></path>
        </symbol>
        <symbol id="ig-info" viewBox="0 0 24 24">
          <circle cx="12" cy="12" r="10"></circle>
          <path d="M12 16v-4M12 8h.01"></path>
        </symbol>
        <symbol id="ig-link" viewBox="0 0 24 24">
          <path
            d="M10 13a5 5 0 0 0 7.1.1l2-2a5 5 0 0 0-7.1-7.1l-1.1 1.1"
          ></path>
          <path d="M14 11a5 5 0 0 0-7.1-.1l-2 2A5 5 0 0 0 12 20l1.1-1.1"></path>
        </symbol>
      </defs>
    </svg>

    <main class="input-group-workflow-grid" aria-label="Input group examples">
      <section
        class="input-group-workflow"
        data-example="input-group-basic"
        aria-labelledby="input-group-basic-title"
      >
        <h2 id="input-group-basic-title">States</h2>
        <div class="field-group">
          <div class="field">
            <label for="ig-default">Default</label>
            <input id="ig-default" placeholder="Placeholder" />
          </div>
          <div class="field">
            <label for="ig-basic">Input group</label>
            <div class="input-group">
              <input id="ig-basic" placeholder="Placeholder" />
            </div>
          </div>
          <div class="field">
            <label for="ig-disabled">Disabled</label>
            <div class="input-group">
              <input
                id="ig-disabled"
                placeholder="This field is disabled"
                disabled
              />
            </div>
          </div>
          <div class="field">
            <label for="ig-invalid">Invalid</label>
            <div class="input-group">
              <input
                id="ig-invalid"
                placeholder="This field is invalid"
                aria-invalid="true"
              />
            </div>
          </div>
        </div>
      </section>

      <section
        class="input-group-workflow"
        data-example="input-group-demo input-group-inline-start input-group-inline-end input-group-kbd"
        aria-labelledby="input-group-position-title"
      >
        <h2 id="input-group-position-title">Inline addons</h2>
        <div class="input-group">
          <input
            ng-model="query"
            placeholder="Search..."
            aria-label="Search documentation"
          />
          <div align="inline-start">
            <svg aria-hidden="true"><use href="#ig-search"></use></svg>
          </div>
          <div align="inline-end">{{ query ? '12 results' : 'No query' }}</div>
        </div>
        <div class="input-group">
          <input
            type="password"
            placeholder="Enter password"
            aria-label="Password"
          />
          <div align="inline-end">
            <svg aria-hidden="true"><use href="#ig-eye-off"></use></svg>
          </div>
        </div>
        <div class="input-group">
          <input id="ig-command-search" placeholder="Search commands..." />
          <label for="ig-command-search">
            <svg aria-hidden="true"><use href="#ig-search"></use></svg>
          </label>
          <div align="inline-end">
            <kbd>⌘K</kbd>
          </div>
        </div>
        <output class="input-group-output">
          Query: {{ query || 'none' }}
        </output>
      </section>

      <section
        class="input-group-workflow"
        data-example="input-group-icon"
        aria-labelledby="input-group-icon-title"
      >
        <h2 id="input-group-icon-title">Icons</h2>
        <div class="input-group">
          <input
            type="email"
            placeholder="Enter your email"
            aria-label="Email with icon"
          />
          <div>
            <svg aria-hidden="true"><use href="#ig-mail"></use></svg>
          </div>
        </div>
        <div class="input-group">
          <input placeholder="Card number" aria-label="Verified card number" />
          <div>
            <svg aria-hidden="true"><use href="#ig-card"></use></svg>
          </div>
          <div align="inline-end">
            <svg aria-hidden="true"><use href="#ig-check"></use></svg>
          </div>
        </div>
        <div class="input-group">
          <input placeholder="Favorite card" aria-label="Favorite card" />
          <div align="inline-end">
            <svg aria-hidden="true"><use href="#ig-star"></use></svg>
            <svg aria-hidden="true"><use href="#ig-info"></use></svg>
          </div>
        </div>
      </section>

      <section
        class="input-group-workflow"
        data-example="input-group-text"
        aria-labelledby="input-group-text-title"
      >
        <h2 id="input-group-text-title">Text addons</h2>
        <div class="input-group">
          <div>
            <span>$</span>
          </div>
          <input inputmode="decimal" placeholder="0.00" aria-label="Amount" />
          <div align="inline-end">
            <span>USD</span>
          </div>
        </div>
        <div class="input-group">
          <div>
            <span>https://</span>
          </div>
          <input placeholder="example.com" aria-label="Website" />
          <div align="inline-end">
            <span>.com</span>
          </div>
        </div>
        <div class="input-group">
          <input
            placeholder="Enter your username"
            aria-label="Company username"
          />
          <div align="inline-end">
            <span>@company.com</span>
          </div>
        </div>
      </section>

      <section
        class="input-group-workflow input-group-workflow-wide"
        data-example="input-group-with-addons"
        aria-labelledby="input-group-addons-title"
      >
        <h2 id="input-group-addons-title">Addon positions</h2>
        <div class="input-group-pair-grid">
          <div class="field">
            <label for="ig-addon-start">Inline start and end</label>
            <div class="input-group">
              <input id="ig-addon-start" />
              <div>
                <svg aria-hidden="true"><use href="#ig-search"></use></svg>
              </div>
              <div align="inline-end">
                <svg aria-hidden="true"><use href="#ig-info"></use></svg>
              </div>
            </div>
          </div>
          <div class="field">
            <label for="ig-addon-header">Block start</label>
            <div class="input-group">
              <input id="ig-addon-header" />
              <div align="block-start">
                <span>First name</span>
                <svg class="input-group-push-end" aria-hidden="true">
                  <use href="#ig-info"></use>
                </svg>
              </div>
            </div>
          </div>
          <div class="field">
            <label for="ig-addon-footer">Block end</label>
            <div class="input-group">
              <input id="ig-addon-footer" />
              <div align="block-end">
                <span>20/240 characters</span>
                <svg class="input-group-push-end" aria-hidden="true">
                  <use href="#ig-info"></use>
                </svg>
              </div>
            </div>
          </div>
          <div class="field">
            <label for="ig-addon-optional">Label and optional text</label>
            <div class="input-group">
              <div>
                <label for="ig-addon-optional">Label</label>
              </div>
              <input id="ig-addon-optional" />
              <div align="inline-end">
                <span>(optional)</span>
              </div>
            </div>
          </div>
        </div>
      </section>

      <section
        class="input-group-workflow"
        data-example="input-group-with-kbd"
        aria-labelledby="input-group-kbd-title"
      >
        <h2 id="input-group-kbd-title">Keyboard hints</h2>
        <div class="input-group">
          <input placeholder="Search for apps..." aria-label="Search apps" />
          <div align="inline-end">Ask AI</div>
          <div align="inline-end">
            <kbd>Tab</kbd>
          </div>
        </div>
        <div class="input-group">
          <input ng-model="username" aria-label="Username" />
          <div align="inline-end">
            <span class="input-group-valid-icon"
              ><svg aria-hidden="true"><use href="#ig-check"></use></svg
            ></span>
          </div>
        </div>
        <p class="input-group-success">This username is available.</p>
        <div class="input-group">
          <input value="angularcss" aria-label="Loading username" disabled />
          <div align="inline-end">
            <output size="sm" aria-label="Loading" class="spinner"></output>
          </div>
        </div>
      </section>

      <section
        class="input-group-workflow"
        data-example="input-group-label"
        aria-labelledby="input-group-label-title"
      >
        <h2 id="input-group-label-title">Labels in addons</h2>
        <div class="input-group">
          <input id="ig-email-name" placeholder="angularcss" />
          <div>
            <label for="ig-email-name">@</label>
          </div>
        </div>
        <div class="input-group">
          <input id="ig-email-address" placeholder="team@angularcss.dev" />
          <div align="block-start">
            <label for="ig-email-address">Email</label>
            <span ng-tooltip class="input-group-push-end">
              <button
                size="icon-xs"
                variant="ghost"
                type="button"
                aria-label="Email help"
              >
                <svg aria-hidden="true"><use href="#ig-info"></use></svg>
              </button>
              <span side="top">We'll use this to send notifications.</span>
            </span>
          </div>
        </div>
      </section>

      <section
        class="input-group-workflow"
        data-example="input-group-button-group"
        aria-labelledby="input-group-button-group-title"
      >
        <h2 id="input-group-button-group-title">Button group</h2>
        <div role="group">
          <label for="ig-url">https://</label>
          <div class="input-group">
            <input id="ig-url" aria-label="URL" />
            <div align="inline-end">
              <svg aria-hidden="true"><use href="#ig-link"></use></svg>
            </div>
          </div>
          <span>.com</span>
        </div>
      </section>

      <section
        class="input-group-workflow input-group-card-workflow"
        data-example="input-group-in-card"
        aria-labelledby="input-group-card-title"
      >
        <article class="card">
          <header>
            <h2 id="input-group-card-title">Card with input group</h2>
            <p>Collect contact details and feedback.</p>
          </header>
          <section>
            <div class="field-group">
              <div class="field">
                <label for="ig-card-email">Email address</label>
                <div class="input-group">
                  <input
                    id="ig-card-email"
                    type="email"
                    placeholder="you@example.com"
                  />
                  <div align="inline-end">
                    <svg aria-hidden="true"><use href="#ig-mail"></use></svg>
                  </div>
                </div>
              </div>
              <div class="field">
                <label for="ig-card-site">Website URL</label>
                <div class="input-group">
                  <div>
                    <span>https://</span>
                  </div>
                  <input id="ig-card-site" placeholder="example.com" />
                  <div align="inline-end">
                    <svg aria-hidden="true"><use href="#ig-link"></use></svg>
                  </div>
                </div>
              </div>
            </div>
          </section>
          <footer class="input-group-card-actions">
            <button
              variant="outline"
              type="button"
              ng-click="cardStatus='Cancelled'"
            >
              Cancel
            </button>
            <button type="button" ng-click="cardStatus='Submitted'">
              Submit
            </button>
            <output class="input-group-output">{{ cardStatus }}</output>
          </footer>
        </article>
      </section>
    </main>
  </body>
</html>

Interactive Compositions

Buttons, dropdown menus, tooltips, popovers, calling-code selection, and mixed Button Group compositions run from AngularTS bindings in the built artifact.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Input Group Compositions</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="copied=false; favorite=false; country='+1'; compositionStatus='Ready'"
    data-example="input-group-compositions"
  >
    <svg class="example-icon-definitions" aria-hidden="true">
      <defs>
        <symbol id="igc-copy" viewBox="0 0 24 24">
          <rect width="14" height="14" x="8" y="8" rx="2"></rect>
          <path
            d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"
          ></path>
        </symbol>
        <symbol id="igc-check" viewBox="0 0 24 24">
          <path d="m5 12 4 4L19 6"></path>
        </symbol>
        <symbol id="igc-star" viewBox="0 0 24 24">
          <path
            d="m12 2 3.1 6.3 6.9 1-5 4.9 1.2 6.8-6.2-3.2L5.8 21 7 14.2 2 9.3l6.9-1Z"
          ></path>
        </symbol>
        <symbol id="igc-info" viewBox="0 0 24 24">
          <circle cx="12" cy="12" r="10"></circle>
          <path d="M12 16v-4M12 8h.01"></path>
        </symbol>
        <symbol id="igc-help" viewBox="0 0 24 24">
          <circle cx="12" cy="12" r="10"></circle>
          <path d="M9.1 9a3 3 0 1 1 5.8 1c0 2-3 2-3 4M12 18h.01"></path>
        </symbol>
        <symbol id="igc-more" viewBox="0 0 24 24">
          <circle cx="5" cy="12" r="1"></circle>
          <circle cx="12" cy="12" r="1"></circle>
          <circle cx="19" cy="12" r="1"></circle>
        </symbol>
        <symbol id="igc-chevron" viewBox="0 0 24 24">
          <path d="m6 9 6 6 6-6"></path>
        </symbol>
        <symbol id="igc-trash" viewBox="0 0 24 24">
          <path d="M3 6h18M8 6V4h8v2M19 6l-1 16H6L5 6M10 11v6M14 11v6"></path>
        </symbol>
      </defs>
    </svg>

    <main
      class="input-group-composition-grid"
      aria-label="Interactive input group compositions"
    >
      <section
        class="input-group-workflow"
        data-example="input-group-button"
        aria-labelledby="igc-button-title"
      >
        <h2 id="igc-button-title">Buttons</h2>
        <div class="input-group">
          <input
            value="https://x.com/angularcss"
            aria-label="Share URL"
            readonly
          />
          <div align="inline-end">
            <button
              size="icon-xs"
              variant="ghost"
              type="button"
              aria-label="Copy URL"
              ng-click="copied=true; compositionStatus='Copied URL'"
            >
              <svg aria-hidden="true">
                <use ng-if="!copied" href="#igc-copy"></use>
                <use ng-if="copied" href="#igc-check"></use>
              </svg>
            </button>
          </div>
        </div>
        <div class="input-group-pill input-group">
          <span>
            <button
              size="icon-xs"
              variant="secondary"
              type="button"
              aria-label="Connection information"
              popovertarget="popover-input-group-compositions-1-content"
            >
              <svg aria-hidden="true"><use href="#igc-info"></use></svg>
            </button>
            <aside
              class="input-group-popover-content"
              aria-label="Connection status"
              id="popover-input-group-compositions-1-content"
              side="bottom"
              align="start"
              popover
            >
              <strong>Your connection is not secure.</strong>
              <p>You should not enter sensitive information on this site.</p>
            </aside>
          </span>
          <div>https://</div>
          <input aria-label="Secure URL" />
          <div align="inline-end">
            <button
              size="icon-xs"
              variant="ghost"
              type="button"
              aria-label="Favorite URL"
              aria-pressed="{{ favorite }}"
              ng-click="favorite=!favorite; compositionStatus=favorite ? 'Added favorite' : 'Removed favorite'"
            >
              <svg aria-hidden="true">
                <use href="#igc-star"></use>
              </svg>
            </button>
          </div>
        </div>
        <div class="input-group">
          <input placeholder="Type to search..." aria-label="Search query" />
          <div align="inline-end">
            <button
              variant="secondary"
              type="button"
              ng-click="compositionStatus='Search submitted'"
            >
              Search
            </button>
          </div>
        </div>
        <output class="input-group-output">{{ compositionStatus }}</output>
      </section>

      <section
        class="input-group-workflow"
        data-example="input-group-with-buttons"
        aria-labelledby="igc-variants-title"
      >
        <h2 id="igc-variants-title">Button variants</h2>
        <div class="input-group">
          <input aria-label="Default action" />
          <div>
            <button type="button" ng-click="compositionStatus='Default action'">
              Default
            </button>
          </div>
        </div>
        <div class="input-group">
          <input aria-label="Outline action" />
          <div>
            <button
              variant="outline"
              type="button"
              ng-click="compositionStatus='Outline action'"
            >
              Outline
            </button>
          </div>
        </div>
        <div class="input-group">
          <input aria-label="Secondary action" />
          <div align="inline-end">
            <button
              variant="secondary"
              type="button"
              ng-click="compositionStatus='Secondary action'"
            >
              Button
            </button>
          </div>
        </div>
        <div class="input-group">
          <input aria-label="Delete action" />
          <div align="inline-end">
            <button
              size="icon-xs"
              variant="secondary"
              type="button"
              aria-label="Delete"
              ng-click="compositionStatus='Deleted'"
            >
              <svg aria-hidden="true"><use href="#igc-trash"></use></svg>
            </button>
          </div>
        </div>
      </section>

      <section
        class="input-group-workflow input-group-menu-workflow"
        data-example="input-group-dropdown"
        aria-labelledby="igc-dropdown-title"
      >
        <h2 id="igc-dropdown-title">Dropdown menus</h2>
        <div class="input-group">
          <input placeholder="Enter file name" aria-label="File name" />
          <div align="inline-end">
            <span ng-dropdown-menu class="input-group-overlay-control">
              <button
                size="icon-xs"
                variant="ghost"
                type="button"
                aria-label="File options"
              >
                <svg aria-hidden="true"><use href="#igc-more"></use></svg>
              </button>
              <menu align="end" style="--menu-width: 10rem">
                <button ng-click="compositionStatus='Settings'">
                  Settings
                </button>
                <button ng-click="compositionStatus='Copied path'">
                  Copy path
                </button>
                <button ng-click="compositionStatus='Opened location'">
                  Open location
                </button>
              </menu>
            </span>
          </div>
        </div>
        <div class="input-group">
          <input
            placeholder="Enter search query"
            aria-label="Search query with scope"
          />
          <div align="inline-end">
            <span ng-dropdown-menu class="input-group-overlay-control">
              <button variant="ghost" type="button">
                Search in
                <svg aria-hidden="true"><use href="#igc-chevron"></use></svg>
              </button>
              <menu align="end" style="--menu-width: 10rem">
                <button ng-click="compositionStatus='Documentation'">
                  Documentation
                </button>
                <button ng-click="compositionStatus='Blog posts'">
                  Blog posts
                </button>
                <button ng-click="compositionStatus='Changelog'">
                  Changelog
                </button>
              </menu>
            </span>
          </div>
        </div>
      </section>

      <section
        class="input-group-workflow"
        data-example="input-group-tooltip"
        aria-labelledby="igc-tooltip-title"
      >
        <h2 id="igc-tooltip-title">Tooltips</h2>
        <div class="input-group">
          <input
            type="password"
            placeholder="Enter password"
            aria-label="Password requirements"
          />
          <div align="inline-end">
            <span ng-tooltip>
              <button
                size="icon-xs"
                variant="ghost"
                type="button"
                aria-label="Password information"
              >
                <svg aria-hidden="true"><use href="#igc-info"></use></svg>
              </button>
              <span side="top">Password must be at least 8 characters.</span>
            </span>
          </div>
        </div>
        <div class="input-group">
          <input
            placeholder="Your email address"
            aria-label="Notification email"
          />
          <div align="inline-end">
            <span ng-tooltip>
              <button
                size="icon-xs"
                variant="ghost"
                type="button"
                aria-label="Email help"
              >
                <svg aria-hidden="true"><use href="#igc-help"></use></svg>
              </button>
              <span side="top">We'll use this to send notifications.</span>
            </span>
          </div>
        </div>
        <div class="input-group">
          <input placeholder="Enter API key" aria-label="API key" />
          <div align="inline-end">
            <span ng-tooltip>
              <button
                size="icon-xs"
                variant="ghost"
                type="button"
                aria-label="API key help"
              >
                <svg aria-hidden="true"><use href="#igc-help"></use></svg>
              </button>
              <span side="left">Click for help with API keys.</span>
            </span>
          </div>
        </div>
      </section>

      <section
        class="input-group-workflow input-group-workflow-wide"
        data-example="input-group-with-tooltip"
        aria-labelledby="igc-mixed-title"
      >
        <h2 id="igc-mixed-title">Mixed interactive controls</h2>
        <div class="input-group-pair-grid">
          <div class="field">
            <label for="igc-tooltip-input">Tooltip</label>
            <div class="input-group">
              <input id="igc-tooltip-input" />
              <div align="inline-end">
                <span ng-tooltip
                  ><button
                    size="icon-xs"
                    variant="ghost"
                    type="button"
                    aria-label="Input information"
                  >
                    <svg aria-hidden="true">
                      <use href="#igc-info"></use>
                    </svg></button
                  ><span side="top">This is content in a tooltip.</span></span
                >
              </div>
            </div>
            <p>This is a description of the input group.</p>
          </div>
          <div class="field">
            <label for="igc-country-input">Dropdown</label>
            <div class="input-group">
              <input id="igc-country-input" type="tel" />
              <div>
                <span ng-dropdown-menu class="input-group-overlay-control">
                  <button variant="ghost" type="button">
                    {{ country }}
                    <svg aria-hidden="true">
                      <use href="#igc-chevron"></use>
                    </svg>
                  </button>
                  <menu align="end" style="--menu-width: 5rem">
                    <button ng-click="country='+1'">+1</button>
                    <button ng-click="country='+44'">+44</button>
                    <button ng-click="country='+46'">+46</button>
                  </menu>
                </span>
              </div>
            </div>
            <p>Select a calling code.</p>
          </div>
          <div class="field">
            <label for="igc-popover-input">Popover</label>
            <div class="input-group">
              <span>
                <button
                  size="icon-xs"
                  variant="secondary"
                  type="button"
                  aria-label="Security details"
                  popovertarget="popover-input-group-compositions-2-content"
                >
                  <svg aria-hidden="true"><use href="#igc-info"></use></svg>
                </button>
                <aside
                  class="input-group-popover-content"
                  aria-label="Security details"
                  id="popover-input-group-compositions-2-content"
                  side="bottom"
                  align="start"
                  popover
                >
                  <strong>Your connection is not secure.</strong>
                  <p>Do not enter sensitive information on this site.</p>
                </aside>
              </span>
              <div>https://</div>
              <input id="igc-popover-input" />
              <div align="inline-end">
                <button
                  size="icon-xs"
                  variant="ghost"
                  type="button"
                  aria-label="Add favorite"
                  ng-click="compositionStatus='Added to favorites'"
                >
                  <svg aria-hidden="true"><use href="#igc-star"></use></svg>
                </button>
              </div>
            </div>
          </div>
          <div class="field">
            <label for="igc-group-url">Button group</label>
            <div role="group">
              <span>https://</span>
              <div class="input-group">
                <input id="igc-group-url" />
                <div align="inline-end">
                  <svg aria-hidden="true"><use href="#igc-info"></use></svg>
                </div>
              </div>
              <span>.com</span>
            </div>
          </div>
        </div>
      </section>
    </main>
  </body>
</html>

Textarea And Block Addons

Block-start and block-end addons, textarea states, a code editor, character counters, and the autosizing custom control remain native form controls.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Input Group Textarea Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="comment=''; commentCount=0; code=''; codeColumn=1; customText=''; customCount=0; textareaStatus='Ready'"
    data-example="input-group-textarea-workflows"
  >
    <svg class="example-icon-definitions" aria-hidden="true">
      <defs>
        <symbol id="igt-copy" viewBox="0 0 24 24">
          <rect width="14" height="14" x="8" y="8" rx="2"></rect>
          <path
            d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"
          ></path>
        </symbol>
        <symbol id="igt-refresh" viewBox="0 0 24 24">
          <path d="M20 11a8 8 0 1 0 2 5M20 4v7h-7"></path>
        </symbol>
        <symbol id="igt-code-icon" viewBox="0 0 24 24">
          <path d="m16 18 6-6-6-6M8 6l-6 6 6 6M14.5 4l-5 16"></path>
        </symbol>
        <symbol id="igt-send" viewBox="0 0 24 24">
          <path d="m22 2-7 20-4-9-9-4ZM22 2 11 13"></path>
        </symbol>
        <symbol id="igt-info" viewBox="0 0 24 24">
          <circle cx="12" cy="12" r="10"></circle>
          <path d="M12 16v-4M12 8h.01"></path>
        </symbol>
      </defs>
    </svg>

    <main
      class="input-group-textarea-grid"
      aria-label="Input group textarea examples"
    >
      <section
        class="input-group-workflow"
        data-example="input-group-block-start"
        aria-labelledby="igt-start-title"
      >
        <h2 id="igt-start-title">Block start</h2>
        <div class="field">
          <label for="igt-start-input">Input</label>
          <div class="input-group">
            <input id="igt-start-input" placeholder="Enter your name" />
            <div align="block-start">
              <span>Full name</span>
            </div>
          </div>
          <p>Header positioned above the input.</p>
        </div>
        <div class="field">
          <label for="igt-start-textarea">Textarea</label>
          <div class="input-group">
            <textarea
              id="igt-start-textarea"
              placeholder="console.log('Hello, world!');"
            ></textarea>
            <div align="block-start" border="true">
              <svg aria-hidden="true"><use href="#igt-code-icon"></use></svg>
              <span class="input-group-mono">script.js</span>
              <button
                size="icon-xs"
                class="input-group-push-end"
                variant="ghost"
                type="button"
                aria-label="Copy code"
                ng-click="textareaStatus='Copied code'"
              >
                <svg aria-hidden="true"><use href="#igt-copy"></use></svg>
              </button>
            </div>
          </div>
        </div>
      </section>

      <section
        class="input-group-workflow"
        data-example="input-group-block-end"
        aria-labelledby="igt-end-title"
      >
        <h2 id="igt-end-title">Block end</h2>
        <div class="field">
          <label for="igt-amount">Input</label>
          <div class="input-group">
            <input
              id="igt-amount"
              inputmode="decimal"
              placeholder="Enter amount"
            />
            <div align="block-end">
              <span>USD</span>
            </div>
          </div>
          <p>Footer positioned below the input.</p>
        </div>
        <div class="field">
          <label for="igt-comment">Textarea</label>
          <div class="input-group">
            <textarea
              id="igt-comment"
              ng-model="comment"
              data-change="commentCount=comment.length"
              maxlength="280"
              placeholder="Write a comment..."
            ></textarea>
            <div align="block-end">
              <span>{{ commentCount }}/280</span>
              <button
                size="sm"
                class="input-group-push-end"
                type="button"
                ng-click="textareaStatus='Posted comment'"
              >
                Post
              </button>
            </div>
          </div>
          <p>Footer positioned below the textarea.</p>
        </div>
      </section>

      <section
        class="input-group-workflow input-group-workflow-wide"
        data-example="input-group-textarea"
        aria-labelledby="igt-editor-title"
      >
        <h2 id="igt-editor-title">Code editor</h2>
        <div class="input-group-code-editor input-group">
          <textarea
            id="igt-code"
            ng-model="code"
            data-change="codeColumn=code.length+1"
            placeholder="console.log('Hello, world!');"
            aria-label="JavaScript code"
          ></textarea>
          <div align="block-start" border="true">
            <span class="input-group-mono"
              ><svg aria-hidden="true"><use href="#igt-code-icon"></use></svg
              >script.js</span
            >
            <button
              size="icon-xs"
              class="input-group-push-end"
              variant="ghost"
              type="button"
              aria-label="Refresh code"
              ng-click="code=''; textareaStatus='Reset code'"
            >
              <svg aria-hidden="true"><use href="#igt-refresh"></use></svg>
            </button>
            <button
              size="icon-xs"
              variant="ghost"
              type="button"
              aria-label="Copy code"
              ng-click="textareaStatus='Copied code'"
            >
              <svg aria-hidden="true"><use href="#igt-copy"></use></svg>
            </button>
          </div>
          <div align="block-end" border="true">
            <span>Line 1, Column {{ codeColumn }}</span>
            <button
              size="sm"
              class="input-group-push-end"
              type="button"
              ng-click="textareaStatus='Ran code'"
            >
              Run
            </button>
          </div>
        </div>
        <output class="input-group-output">{{ textareaStatus }}</output>
      </section>

      <section
        class="input-group-workflow input-group-workflow-wide"
        data-example="input-group-textarea-examples"
        aria-labelledby="igt-examples-title"
      >
        <h2 id="igt-examples-title">Textarea states and addons</h2>
        <div class="input-group-pair-grid">
          <div class="field">
            <label for="igt-default-textarea">Default textarea</label>
            <textarea
              id="igt-default-textarea"
              placeholder="Enter your text here..."
            ></textarea>
          </div>
          <div class="field">
            <label for="igt-invalid-textarea">Invalid</label>
            <div class="input-group">
              <textarea
                id="igt-invalid-textarea"
                aria-invalid="true"
                placeholder="Enter your text here..."
              ></textarea>
            </div>
          </div>
          <div class="field">
            <label for="igt-disabled-textarea">Disabled</label>
            <div class="input-group">
              <textarea
                id="igt-disabled-textarea"
                disabled
                placeholder="Enter your text here..."
              ></textarea>
            </div>
          </div>
          <div class="field">
            <label for="igt-prompt">Addon (block start)</label>
            <div class="input-group">
              <textarea id="igt-prompt"></textarea>
              <div align="block-start">
                <span>Ask, search or chat...</span
                ><svg class="input-group-push-end" aria-hidden="true">
                  <use href="#igt-info"></use>
                </svg>
              </div>
            </div>
          </div>
          <div class="field">
            <label for="igt-send-comment">Addon (send)</label>
            <div class="input-group">
              <textarea
                id="igt-send-comment"
                ng-model="comment"
                data-change="commentCount=comment.length"
                placeholder="Enter your text here..."
              ></textarea>
              <div align="block-end">
                <span>{{ commentCount }}/280 characters</span
                ><button
                  size="icon-xs"
                  class="input-group-push-end input-group-round-button"
                  type="button"
                  aria-label="Send"
                  ng-click="textareaStatus='Sent message'"
                >
                  <svg aria-hidden="true"><use href="#igt-send"></use></svg>
                </button>
              </div>
            </div>
          </div>
          <div class="field">
            <label for="igt-actions">Addon (buttons)</label>
            <div class="input-group">
              <textarea
                id="igt-actions"
                placeholder="Share your thoughts..."
              ></textarea>
              <div align="block-end">
                <button
                  size="sm"
                  class="input-group-push-end"
                  variant="ghost"
                  type="button"
                  ng-click="textareaStatus='Cancelled comment'"
                >
                  Cancel</button
                ><button
                  size="sm"
                  type="button"
                  ng-click="textareaStatus='Posted comment'"
                >
                  Post comment
                </button>
              </div>
            </div>
          </div>
        </div>
      </section>

      <section
        class="input-group-workflow"
        data-example="input-group-custom"
        aria-labelledby="igt-custom-title"
      >
        <h2 id="igt-custom-title">Autosizing custom control</h2>
        <div class="input-group">
          <textarea
            class="input-group-autosize"
            ng-model="customText"
            data-change="customCount=customText.length"
            placeholder="Autoresize textarea..."
            aria-label="Autosize textarea"
          ></textarea>
          <div align="block-end">
            <span>{{ customCount }} characters</span
            ><button
              size="sm"
              class="input-group-push-end"
              type="button"
              ng-click="textareaStatus='Submitted custom text'"
            >
              Submit
            </button>
          </div>
        </div>
      </section>
    </main>
  </body>
</html>

Right To Left

Logical addon placement and AngularTS model updates work without RTL-specific component markup.

View source
<!doctype html>
<html lang="ar" dir="rtl">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Input Group Rtl</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="rtlQuery=''; rtlComment=''; rtlCount=0; rtlStatus='جاهز'"
    data-example="input-group-rtl"
  >
    <main
      class="input-group-rtl-workflow"
      aria-label="مجموعات إدخال من اليمين إلى اليسار"
    >
      <div class="input-group">
        <input ng-model="rtlQuery" placeholder="بحث..." aria-label="بحث" />
        <div align="inline-start">
          <svg viewBox="0 0 24 24" aria-hidden="true">
            <circle cx="11" cy="11" r="8"></circle>
            <path d="m21 21-4.3-4.3"></path>
          </svg>
        </div>
        <div align="inline-end">١٢ نتيجة</div>
      </div>
      <div class="input-group">
        <input placeholder="جاري البحث..." aria-label="جاري البحث" />
        <div align="inline-end">
          <output size="sm" aria-label="تحميل" class="spinner"></output>
        </div>
      </div>
      <div class="input-group">
        <input placeholder="جاري حفظ التغييرات..." aria-label="جاري الحفظ" />
        <div align="inline-end">
          <span>جاري الحفظ...</span
          ><output size="sm" aria-label="تحميل" class="spinner"></output>
        </div>
      </div>
      <div class="field">
        <label for="input-group-rtl-comment">منطقة النص</label>
        <div class="input-group">
          <textarea
            id="input-group-rtl-comment"
            ng-model="rtlComment"
            data-change="rtlCount=rtlComment.length"
            maxlength="280"
            placeholder="اكتب تعليقًا..."
          ></textarea>
          <div align="block-end">
            <span>{{ rtlCount }}/٢٨٠</span>
            <button
              size="sm"
              class="input-group-push-end"
              type="button"
              ng-click="rtlStatus='تم النشر'"
            >
              نشر
            </button>
          </div>
        </div>
        <p>تذييل موضع أسفل منطقة النص.</p>
      </div>
      <output class="input-group-output">
        {{ rtlStatus }} · {{ rtlQuery || 'لا يوجد بحث' }}
      </output>
    </main>
  </body>
</html>

Addon States

Visible addons participate in the control description. AngularCSS preserves external description IDs as AngularTS inserts or hides addon content.

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Input Group State Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="query='AngularCSS'; showCurrency=false; priceHidden=false"
  >
    <main class="component-state-grid" aria-label="Input group state contracts">
      <section
        class="component-state-section"
        aria-labelledby="described-group-title"
      >
        <h2 id="described-group-title">Described addons</h2>
        <p id="external-help" class="component-state-help">
          Enter an invoice total.
        </p>
        <div id="described-group" class="input-group">
          <input
            aria-label="Invoice total"
            aria-describedby="external-help currency-code"
          />
          <span id="currency-code">USD</span>
          <span align="inline-end" aria-hidden="true"> .00 </span>
        </div>
      </section>

      <section
        class="component-state-section"
        aria-labelledby="button-group-title"
      >
        <h2 id="button-group-title">Action button</h2>
        <div id="button-group" class="input-group">
          <input aria-label="Documentation search" ng-model="query" />
          <button type="button" ng-click="query=''">Clear</button>
        </div>
      </section>

      <section
        class="component-state-section"
        aria-labelledby="dynamic-group-title"
      >
        <h2 id="dynamic-group-title">Conditional addon</h2>
        <div id="dynamic-group" class="input-group">
          <input
            ng-attr-aria-label="{{ showCurrency ? 'Budget in USD' : 'Budget' }}"
            aria-describedby="budget-help"
          />
          <span ng-if="showCurrency" id="dynamic-addon"> USD </span>
        </div>
        <p id="budget-help" class="component-state-help">Monthly budget</p>
        <button
          variant="outline"
          type="button"
          ng-click="showCurrency=true"
          ng-disabled="showCurrency"
        >
          Add currency
        </button>
      </section>

      <section
        class="component-state-section"
        aria-labelledby="hidden-group-title"
      >
        <h2 id="hidden-group-title">Hidden addon</h2>
        <div id="hidden-group" class="input-group">
          <input aria-label="Price" aria-describedby="price-help" />
          <span id="addon-price" ng-attr-aria-hidden="{{ priceHidden }}">
            USD
          </span>
        </div>
        <p id="price-help" class="component-state-help">Price before tax</p>
        <button
          variant="outline"
          type="button"
          ng-click="priceHidden=!priceHidden"
        >
          Toggle currency description
        </button>
      </section>
    </main>
  </body>
</html>

Clicking a non-button addon focuses the grouped control. Interactive addon content remains responsible for its own native or composed behavior.

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Grouped native controls and addons.

Anatomy

Root styling selector

  • .input-group

Semantic structure

Use one native input, textarea, select, combobox, or spinbutton inside .input-group. Addons may be placed at inline-start, inline-end, block-start, or block-end with align. Buttons, menus, tooltips, and popovers retain their own behavior.

API

Attributes and state

AttributeAccessPurpose
alignAuthoredDirect addon placement: inline-start, inline-end, block-start, or block-end.
aria-invalidAuthoredValidation state exposed to assistive technology and CSS.
borderAuthoredUse true on a direct block addon to draw its dividing border.
sizeAuthoredDirect action size: sm, icon-xs, or icon-sm; omit for the compact addon action.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Input Group is styling-only. Native controls own focus, values, validation, and submission. Use a native label addon when clicking addon text should focus the control; AngularTS owns dynamic text and actions.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Keep one clearly labeled native control in each group. Use aria-describedby for explanatory addon text, aria-hidden for decorative text, and a native label for when an addon should focus the control.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

17 - input-otp

A native one-time-code input with a segmented visual treatment.

Use one native input. The browser owns editing, paste, autofill, and validation.

<label for="code">One-time code</label>
<input
  id="code"
  autocomplete="one-time-code"
  inputmode="numeric"
  pattern="[0-9]{6}"
  maxlength="6"
  ng-model="code"
/>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Input Otp</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="otp='123456'"
    data-example="input-otp-demo"
  >
    <div class="stack-sm">
      <label for="one-time-code">One-time code</label>
      <input
        id="one-time-code"
        class="visual-example"
        name="one-time-code"
        inputmode="numeric"
        autocomplete="one-time-code"
        pattern="[0-9]{6}"
        minlength="6"
        maxlength="6"
        size="6"
        ng-model="otp"
        required
      />
      <output class="visually-hidden" aria-live="polite">
        Code: {{ otp }}
      </output>
    </div>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. One native one-time-code input.

Anatomy

Root styling selector

  • input[autocomplete="one-time-code"]

Semantic structure

Use one native input with autocomplete="one-time-code". The standard autocomplete purpose identifies the segmented one-time-code presentation; input mode, length, and pattern remain native attributes.

API

Attributes and state

AttributeAccessPurpose
aria-invalidAuthoredValidation state exposed to assistive technology and CSS.
groupAuthoredOptional visual grouping size. Use 3 to separate a six-character code into two groups.
maxlengthAuthoredMaximum native text length.
patternAuthoredNative regular-expression validation constraint.
sizeAuthoredNative visible-character count; AngularCSS supports four or six code cells.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

VariablePurpose
--otp-cell-sizeWidth of one visual code cell; defaults to eight spacing units.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Input OTP is one styling-only native input. The browser owns typing, editing, paste, password-manager autofill, autocomplete=one-time-code, input mode, length, pattern validation, and form submission; AngularTS ng-model owns application state. AngularCSS registers no input-otp directive.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Associate every control with a visible label. Preserve native required, disabled, and invalid semantics, and connect help or error text with aria-describedby.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

18 - item

Flexible list item primitive

Items compose media, content, title, description, and actions.

<div variant="outline" class="item">
  <section>
    <h3>Item title</h3>
    <p>Supporting description.</p>
  </section>
</div>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Item</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak>
    <ul style="max-width: 32rem">
      <li variant="outline" id="outline-item" class="item">
        <figure variant="icon">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            stroke-width="1.75"
            stroke="currentColor"
          >
            <path
              stroke-linecap="round"
              stroke-linejoin="round"
              d="M9 12.75 11.25 15 15 9.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
            />
          </svg>
        </figure>
        <section>
          <h3>Profile verified</h3>
          <p>Your public display name and email have been confirmed.</p>
        </section>
        <menu>
          <button variant="outline" size="sm">Review</button>
        </menu>
      </li>
      <li variant="muted" size="sm" id="compact-item" class="item">
        <section>
          <h3>Scheduled reports</h3>
          <p>Weekly snapshots are ready for your team.</p>
        </section>
        <menu>
          <span variant="secondary" class="badge">New</span>
        </menu>
      </li>
      <li aria-disabled="true" id="disabled-item" class="item">
        <section>
          <h3>Archived workspace</h3>
          <p>This workspace is retained for audit history.</p>
        </section>
        <menu>
          <button variant="outline" size="sm" disabled>Restore</button>
        </menu>
      </li>
    </ul>
  </body>
</html>

Workflows

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Item Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak ng-init="itemState={message:'Ready'}">
    <main class="item-workflow-grid" aria-label="Item workflows">
      <section data-example="item-demo" class="item-workflow">
        <ul>
          <li variant="outline" class="item">
            <section>
              <h3>Basic Item</h3>
              <p>A simple item with title and description.</p>
            </section>
            <menu>
              <button
                variant="outline"
                size="sm"
                type="button"
                ng-click="itemState.message='Basic action'"
              >
                Action
              </button>
            </menu>
          </li>
          <li variant="outline" size="sm" href="#verified" class="item">
            <figure>
              <svg viewBox="0 0 24 24" aria-hidden="true">
                <path d="M9 12.75 11.25 15 15 9.75"></path>
                <circle cx="12" cy="12" r="9"></circle>
              </svg>
            </figure>
            <section>
              <h3>Your profile has been verified.</h3>
            </section>
            <menu aria-hidden="true"></menu>
          </li>
        </ul>
      </section>

      <section data-example="item-avatar" class="item-workflow">
        <ul>
          <li variant="outline" class="item">
            <figure>
              <span class="item-avatar-large avatar"
                ><img src="../../images/avatars/01.png" alt="Evil Rabbit"
              /></span>
            </figure>
            <section>
              <h3>Evil Rabbit</h3>
              <p>Last seen 5 months ago</p>
            </section>
            <menu>
              <button
                variant="outline"
                size="icon-sm"
                type="button"
                aria-label="Invite Evil Rabbit"
              >
                +
              </button>
            </menu>
          </li>
          <li variant="outline" class="item">
            <figure class="item-avatar-stack">
              <span class="avatar"
                ><img
                  src="../../images/avatars/02.png"
                  alt="Jordan Lee" /></span
              ><span class="avatar"
                ><img src="../../images/avatars/03.png" alt="maxleiter" /></span
              ><span class="avatar"
                ><img src="../../images/avatars/01.png" alt="evilrabbit"
              /></span>
            </figure>
            <section>
              <h3>No Team Members</h3>
              <p>Invite your team to collaborate on this project.</p>
            </section>
            <menu>
              <button
                variant="outline"
                size="sm"
                type="button"
                ng-click="itemState.message='Invite opened'"
              >
                Invite
              </button>
            </menu>
          </li>
        </ul>
      </section>

      <section data-example="item-icon" class="item-workflow">
        <article variant="outline" class="item">
          <figure variant="icon">
            <svg viewBox="0 0 24 24" aria-hidden="true">
              <path
                d="M12 9v4m0 4h.01M10.3 3.7 2.5 17.2A2 2 0 0 0 4.2 20h15.6a2 2 0 0 0 1.7-2.8L13.7 3.7a2 2 0 0 0-3.4 0Z"
              ></path>
            </svg>
          </figure>
          <section>
            <h3>Security Alert</h3>
            <p>New login detected from unknown device.</p>
          </section>
          <menu>
            <button variant="outline" size="sm" type="button">Review</button>
          </menu>
        </article>
      </section>

      <section data-example="item-image" class="item-workflow">
        <ul>
          <li variant="outline" href="#midnight" class="item">
            <figure variant="image">
              <img
                src="../../images/avatars/01.png"
                alt="Midnight City Lights"
              />
            </figure>
            <section>
              <h3>Midnight City Lights - Electric Nights</h3>
              <p>Neon Dreams</p>
            </section>
            <section>
              <p>3:45</p>
            </section>
          </li>
          <li variant="outline" href="#coffee" class="item">
            <figure variant="image">
              <img
                src="../../images/avatars/02.png"
                alt="Coffee Shop Conversations"
              />
            </figure>
            <section>
              <h3>Coffee Shop Conversations - Urban Stories</h3>
              <p>The Morning Brew</p>
            </section>
            <section>
              <p>4:05</p>
            </section>
          </li>
          <li variant="outline" href="#digital" class="item">
            <figure variant="image">
              <img src="../../images/avatars/03.png" alt="Digital Rain" />
            </figure>
            <section>
              <h3>Digital Rain - Binary Beats</h3>
              <p>Cyber Symphony</p>
            </section>
            <section>
              <p>3:30</p>
            </section>
          </li>
        </ul>
      </section>

      <section
        data-example="item-dropdown"
        class="item-workflow item-dropdown-workflow"
      >
        <div ng-dropdown-menu>
          <button variant="outline" type="button">
            Select <span aria-hidden="true"></span>
          </button>
          <menu>
            <section>
              <button ng-click="itemState.message='Selected Jordan Lee'">
                <article size="xs" class="item">
                  <figure>
                    <span class="avatar"
                      ><img src="../../images/avatars/02.png" alt=""
                    /></span>
                  </figure>
                  <section>
                    <h3>Jordan Lee</h3>
                    <p>jordan@example.com</p>
                  </section>
                </article></button
              ><button ng-click="itemState.message='Selected maxleiter'">
                <article size="xs" class="item">
                  <figure>
                    <span class="avatar"
                      ><img src="../../images/avatars/03.png" alt=""
                    /></span>
                  </figure>
                  <section>
                    <h3>maxleiter</h3>
                    <p>maxleiter@vercel.com</p>
                  </section>
                </article></button
              ><button ng-click="itemState.message='Selected evilrabbit'">
                <article size="xs" class="item">
                  <figure>
                    <span class="avatar"
                      ><img src="../../images/avatars/01.png" alt=""
                    /></span>
                  </figure>
                  <section>
                    <h3>evilrabbit</h3>
                    <p>evilrabbit@vercel.com</p>
                  </section>
                </article>
              </button>
            </section>
          </menu>
        </div>
      </section>

      <section data-example="item-group" class="item-workflow">
        <ul>
          <li variant="outline" class="item">
            <figure>
              <span class="avatar"
                ><img src="../../images/avatars/02.png" alt="Jordan Lee"
              /></span>
            </figure>
            <section>
              <h3>Jordan Lee</h3>
              <p>jordan@example.com</p>
            </section>
            <menu>
              <button
                variant="ghost"
                size="icon-sm"
                type="button"
                aria-label="Invite Jordan Lee"
              >
                +
              </button>
            </menu>
          </li>
          <li variant="outline" class="item">
            <figure>
              <span class="avatar"
                ><img src="../../images/avatars/03.png" alt="maxleiter"
              /></span>
            </figure>
            <section>
              <h3>maxleiter</h3>
              <p>maxleiter@vercel.com</p>
            </section>
            <menu>
              <button
                variant="ghost"
                size="icon-sm"
                type="button"
                aria-label="Invite maxleiter"
              >
                +
              </button>
            </menu>
          </li>
          <li variant="outline" class="item">
            <figure>
              <span class="avatar"
                ><img src="../../images/avatars/01.png" alt="evilrabbit"
              /></span>
            </figure>
            <section>
              <h3>evilrabbit</h3>
              <p>evilrabbit@vercel.com</p>
            </section>
            <menu>
              <button
                variant="ghost"
                size="icon-sm"
                type="button"
                aria-label="Invite evilrabbit"
              >
                +
              </button>
            </menu>
          </li>
        </ul>
      </section>

      <section
        data-example="item-header"
        class="item-workflow item-workflow-wide"
      >
        <ul class="item-header-grid">
          <li variant="outline" class="item">
            <header class="item-header">
              <img src="../../images/avatars/01.png" alt="v0-1.5-sm" />
            </header>
            <section>
              <h3>v0-1.5-sm</h3>
              <p>Everyday tasks and UI generation.</p>
            </section>
          </li>
          <li variant="outline" class="item">
            <header class="item-header">
              <img src="../../images/avatars/02.png" alt="v0-1.5-lg" />
            </header>
            <section>
              <h3>v0-1.5-lg</h3>
              <p>Advanced thinking or reasoning.</p>
            </section>
          </li>
          <li variant="outline" class="item">
            <header class="item-header">
              <img src="../../images/avatars/03.png" alt="v0-2.0-mini" />
            </header>
            <section>
              <h3>v0-2.0-mini</h3>
              <p>Open Source model for everyone.</p>
            </section>
          </li>
        </ul>
      </section>

      <section data-example="item-link" class="item-workflow">
        <ul>
          <li href="#documentation" class="item">
            <section>
              <h3>Visit our documentation</h3>
              <p>Learn how to get started with our components.</p>
            </section>
            <menu aria-hidden="true"></menu>
          </li>
          <li variant="outline" href="#external" class="item">
            <section>
              <h3>External resource</h3>
              <p>Opens in a new tab with security attributes.</p>
            </section>
            <menu aria-hidden="true"></menu>
          </li>
        </ul>
      </section>

      <section data-example="item-size" class="item-workflow">
        <ul>
          <li variant="outline" class="item">
            <figure variant="icon"></figure>
            <section>
              <h3>Default Size</h3>
              <p>The standard size for most use cases.</p>
            </section>
          </li>
          <li variant="outline" size="sm" class="item">
            <figure variant="icon"></figure>
            <section>
              <h3>Small Size</h3>
              <p>A compact size for dense layouts.</p>
            </section>
          </li>
          <li variant="outline" size="xs" class="item">
            <figure variant="icon"></figure>
            <section>
              <h3>Extra Small Size</h3>
              <p>The most compact size available.</p>
            </section>
          </li>
        </ul>
      </section>

      <section data-example="item-variant" class="item-workflow">
        <ul>
          <li class="item">
            <figure variant="icon"></figure>
            <section>
              <h3>Default Variant</h3>
              <p>Transparent background with no border.</p>
            </section>
          </li>
          <li variant="outline" class="item">
            <figure variant="icon"></figure>
            <section>
              <h3>Outline Variant</h3>
              <p>Outlined style with a visible border.</p>
            </section>
          </li>
          <li variant="muted" class="item">
            <figure variant="icon"></figure>
            <section>
              <h3>Muted Variant</h3>
              <p>Muted background for secondary content.</p>
            </section>
          </li>
        </ul>
      </section>

      <section data-example="muted-item-group" class="item-workflow">
        <ul>
          <li variant="muted" ng-repeat="number in [1,2,3]" class="item">
            <section>
              <h3>Item {{ number }}</h3>
              <p>Item in muted group.</p>
            </section>
            <menu>
              <button variant="outline" size="sm" type="button">Action</button>
            </menu>
          </li>
        </ul>
      </section>

      <section data-example="outline-item-group" class="item-workflow">
        <ul>
          <li variant="outline" ng-repeat="number in [1,2,3]" class="item">
            <figure variant="icon"></figure>
            <section>
              <h3>Item {{ number }}</h3>
              <p>Item with icon.</p>
            </section>
          </li>
        </ul>
      </section>

      <section
        data-example="file-upload-list"
        class="item-workflow item-workflow-wide"
      >
        <ul>
          <li
            size="xs"
            class="file-upload-item item"
            ng-repeat="file in [{name:'document.pdf',progress:45,time:'2m 30s'},{name:'presentation.pptx',progress:78,time:'45s'},{name:'spreadsheet.xlsx',progress:12,time:'5m 12s'},{name:'image.jpg',progress:100,time:'Complete'}]"
          >
            <figure variant="icon">
              <svg viewBox="0 0 24 24" aria-hidden="true">
                <path
                  d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"
                ></path>
                <path d="M14 2v6h6"></path>
              </svg>
            </figure>
            <section>
              <h3>{{ file.name }}</h3>
            </section>
            <section class="file-upload-progress">
              <progress
                value="{{ file.progress }}"
                max="100"
                aria-label="Upload progress for {{ file.name }}"
              ></progress>
            </section>
            <menu class="file-upload-time">{{ file.time }}</menu>
          </li>
        </ul>
      </section>

      <section
        data-example="item-rtl"
        class="item-workflow"
        dir="rtl"
        lang="ar"
      >
        <ul>
          <li variant="outline" class="item">
            <section>
              <h3>عنصر أساسي</h3>
              <p>عنصر بسيط يحتوي على عنوان ووصف.</p>
            </section>
            <menu>
              <button variant="outline" size="sm" type="button">إجراء</button>
            </menu>
          </li>
          <li variant="outline" size="sm" href="#verified-rtl" class="item">
            <figure></figure>
            <section>
              <h3>تم التحقق من ملفك الشخصي.</h3>
            </section>
            <menu aria-hidden="true"></menu>
          </li>
        </ul>
      </section>

      <output class="item-workflow-output">{{ itemState.message }}</output>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Semantic repeated-content composition.

Anatomy

Root styling selector

  • .item

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

AttributeAccessPurpose
sizeAuthoredItem density: xs or sm; omit for the default size.
variantAuthoredItem surface: outline or muted; direct figures additionally accept icon or image.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Semantic repeated-content composition. AngularCSS supplies styling without a runtime directive. Native HTML owns platform behavior; AngularTS owns application values, commands, and authored state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Prefer semantic landmarks and native elements inside the layout. Any interactive handles or triggers must retain an accessible name and visible focus indicator.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

19 - pagination

Page navigation links

Use nav with aria-label="pagination" and mark the current page with aria-current="page".

<nav aria-label="pagination" class="pagination">
  <ul>
    <li>
      <a href="#">1</a>
    </li>
    <li>
      <a aria-current="page" href="#">2</a>
    </li>
  </ul>
</nav>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Pagination</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="pagination-demo">
    <main class="visual-example">
      <nav aria-label="pagination" class="pagination">
        <ul>
          <li>
            <a href="#previous" rel="prev" aria-label="Go to previous page">
              <svg
                icon="inline-start"
                aria-hidden="true"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <path d="m15 18-6-6 6-6"></path>
              </svg>
              <span>Previous</span>
            </a>
          </li>
          <li>
            <a href="#page-1">1</a>
          </li>
          <li>
            <a href="#page-2" aria-current="page">2</a>
          </li>
          <li>
            <a href="#page-3">3</a>
          </li>
          <li>
            <span aria-hidden="true">
              <svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
                <circle cx="5" cy="12" r="1.5"></circle>
                <circle cx="12" cy="12" r="1.5"></circle>
                <circle cx="19" cy="12" r="1.5"></circle>
              </svg>
              <span>More pages</span>
            </span>
          </li>
          <li>
            <a href="#next" rel="next" aria-label="Go to next page">
              <span>Next</span>
              <svg
                icon="inline-end"
                aria-hidden="true"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <path d="m9 18 6-6-6-6"></path>
              </svg>
            </a>
          </li>
        </ul>
      </nav>
    </main>
  </body>
</html>

Workflows

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Pagination Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="paginationWorkflow={showPage4:false,activePage:2,nextDisabled:false,rows:'25'}"
    data-example="pagination-icons-only pagination-rtl pagination-simple"
  >
    <main class="visual-example">
      <section aria-labelledby="pagination-dynamic-heading">
        <header>
          <h2 id="pagination-dynamic-heading">Application state</h2>
          <div class="component-state-actions">
            <button
              type="button"
              variant="outline"
              size="sm"
              ng-click="paginationWorkflow.showPage4=!paginationWorkflow.showPage4; paginationWorkflow.activePage=paginationWorkflow.showPage4 ? 4 : 2"
            >
              {{ paginationWorkflow.showPage4 ? 'Remove page 4' : 'Add page 4'
              }}
            </button>
            <button
              type="button"
              variant="outline"
              size="sm"
              ng-click="paginationWorkflow.nextDisabled=!paginationWorkflow.nextDisabled"
            >
              {{ paginationWorkflow.nextDisabled ? 'Enable next' : 'Disable
              next' }}
            </button>
          </div>
        </header>
        <nav
          aria-label="Dynamic pagination"
          id="dynamic-pagination"
          class="pagination"
        >
          <ul>
            <li>
              <a
                href="#page-1"
                ng-click="paginationWorkflow.activePage=1"
                aria-current="{{ paginationWorkflow.activePage === 1 ? 'page' : 'false' }}"
                >1</a
              >
            </li>
            <li>
              <a
                href="#page-2"
                ng-click="paginationWorkflow.activePage=2"
                aria-current="{{ paginationWorkflow.activePage === 2 ? 'page' : 'false' }}"
                >2</a
              >
            </li>
            <li>
              <a
                href="#page-3"
                ng-click="paginationWorkflow.activePage=3"
                aria-current="{{ paginationWorkflow.activePage === 3 ? 'page' : 'false' }}"
                >3</a
              >
            </li>
            <li ng-if="paginationWorkflow.showPage4">
              <a
                href="#page-4"
                ng-click="paginationWorkflow.activePage=4"
                aria-current="{{ paginationWorkflow.activePage === 4 ? 'page' : 'false' }}"
                >4</a
              >
            </li>
            <li>
              <a
                href="#next"
                rel="next"
                aria-label="Go to next page"
                aria-disabled="{{ paginationWorkflow.nextDisabled }}"
              >
                <span>Next</span>
                <svg
                  icon="inline-end"
                  aria-hidden="true"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                >
                  <path d="m9 18 6-6-6-6"></path>
                </svg>
              </a>
            </li>
          </ul>
        </nav>
      </section>

      <section aria-labelledby="pagination-simple-heading">
        <header>
          <h2 id="pagination-simple-heading">Simple</h2>
        </header>
        <nav aria-label="Simple pagination" class="pagination">
          <ul>
            <li>
              <a href="#simple-1">1</a>
            </li>
            <li>
              <a href="#simple-2" aria-current="page">2</a>
            </li>
            <li>
              <a href="#simple-3">3</a>
            </li>
            <li>
              <a href="#simple-4">4</a>
            </li>
            <li>
              <a href="#simple-5">5</a>
            </li>
          </ul>
        </nav>
      </section>

      <section aria-labelledby="pagination-icons-heading">
        <header>
          <h2 id="pagination-icons-heading">Rows</h2>
        </header>
        <div class="pagination-compact-row">
          <label class="pagination-rows-field" for="pagination-rows-per-page">
            <span>Rows per page</span>
            <select
              id="pagination-rows-per-page"
              ng-model="paginationWorkflow.rows"
            >
              <option value="10">10</option>
              <option value="25">25</option>
              <option value="50">50</option>
              <option value="100">100</option>
            </select>
          </label>
          <nav aria-label="Compact pagination" class="pagination">
            <ul>
              <li>
                <a
                  href="#compact-previous"
                  rel="prev"
                  aria-label="Go to previous page"
                >
                  <svg
                    icon="inline-start"
                    aria-hidden="true"
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                  >
                    <path d="m15 18-6-6 6-6"></path>
                  </svg>
                </a>
              </li>
              <li>
                <a href="#compact-next" rel="next" aria-label="Go to next page">
                  <svg
                    icon="inline-end"
                    aria-hidden="true"
                    viewBox="0 0 24 24"
                    fill="none"
                    stroke="currentColor"
                    stroke-width="2"
                  >
                    <path d="m9 18 6-6-6-6"></path>
                  </svg>
                </a>
              </li>
            </ul>
          </nav>
        </div>
        <output class="workflow-output">
          Rows: <span ng-bind="paginationWorkflow.rows"></span>
        </output>
      </section>

      <section aria-labelledby="pagination-rtl-heading" lang="ar">
        <header>
          <h2 id="pagination-rtl-heading">الصفحات</h2>
        </header>
        <nav
          dir="rtl"
          aria-label="ترقيم الصفحات"
          id="rtl-pagination"
          class="pagination"
        >
          <ul>
            <li>
              <a
                href="#rtl-previous"
                rel="prev"
                aria-label="الانتقال إلى الصفحة السابقة"
              >
                <svg
                  icon="inline-start"
                  aria-hidden="true"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                >
                  <path d="m15 18-6-6 6-6"></path>
                </svg>
                <span>السابق</span>
              </a>
            </li>
            <li>
              <a href="#rtl-1">١</a>
            </li>
            <li>
              <a href="#rtl-2" aria-current="page">٢</a>
            </li>
            <li>
              <a href="#rtl-3">٣</a>
            </li>
            <li>
              <span>
                <svg aria-hidden="true" viewBox="0 0 24 24" fill="currentColor">
                  <circle cx="5" cy="12" r="1.5"></circle>
                  <circle cx="12" cy="12" r="1.5"></circle>
                  <circle cx="19" cy="12" r="1.5"></circle>
                </svg>
                <span>صفحات إضافية</span>
              </span>
            </li>
            <li>
              <a
                href="#rtl-next"
                rel="next"
                aria-label="الانتقال إلى الصفحة التالية"
              >
                <span>التالي</span>
                <svg
                  icon="inline-end"
                  aria-hidden="true"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                >
                  <path d="m9 18 6-6-6-6"></path>
                </svg>
              </a>
            </li>
          </ul>
        </nav>
      </section>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Native navigation, lists, and links.

Anatomy

Root styling selector

  • .pagination

Semantic structure

Apply .pagination to a native nav containing a ul or ol with direct li children. The class distinguishes Pagination from other navigation landmarks; page, previous, and next controls remain native links. Ellipsis is optional. Compose rows-per-page controls beside Pagination with existing native form components; Pagination does not own that model.

API

Attributes and state

AttributeAccessPurpose
aria-currentAuthoredCurrent item or date state.
aria-disabledAuthoredSemantic disabled state.
dirAuthoredText and interaction direction: ltr or rtl.
relAuthoredUse the prev or next link type for directional pagination controls.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Native navigation, lists, list items, and links own pagination semantics and navigation. URLs, routing, page counts, rows-per-page values, and current-page application state remain AngularTS or application concerns. AngularCSS registers no pagination directive.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use a native nav landmark with an accessible label, a native list, and native links. Expose exactly one current destination with aria-current="page". Previous and next links need destination-specific accessible names; ellipsis is decorative and removed from the accessibility tree.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

20 - popover

Floating rich content panels

Connect a native button to semantic popover content with popovertarget and popover. The browser owns top-layer rendering, Escape, and light dismissal.

<span>
  <button popovertarget="dimensions">Open</button>
  <aside id="dimensions" popover>Content</aside>
</span>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Popover</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="popover-demo">
    <main class="visual-example">
      <span aria-label="Dimensions popover">
        <button
          type="button"
          variant="outline"
          popovertarget="popover-popover-1-content"
        >
          Open popover
        </button>
        <aside
          aria-label="Dimensions"
          id="popover-popover-1-content"
          side="bottom"
          align="center"
          popover
        >
          <header>
            <h2>Dimensions</h2>
            <p>Set the dimensions for the layer.</p>
          </header>
          <form>
            <label
              ><span>Width</span>
              <input id="popover-width" value="100%" autofocus />
            </label>
            <label
              ><span>Max. width</span>
              <input id="popover-max-width" value="300px" />
            </label>
            <label
              ><span>Height</span>
              <input id="popover-height" value="25px" />
            </label>
            <label
              ><span>Max. height</span>
              <input id="popover-max-height" value="none" />
            </label>
          </form>
        </aside>
      </span>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Native Popover API disclosure.

Anatomy

Root styling selector

  • span:has(> [popovertarget] ~ [popover])

Semantic structure

Connect a native button’s popovertarget to one element with the matching id and popover. Header, title, and description selectors are optional styling hooks. Use native form controls inside the content; AngularTS owns their values and validation.

API

Attributes and state

AttributeAccessPurpose
alignAuthoredPopover alignment: start, center, or end.
popoverAuthoredNative Popover API state and behavior on the surface.
popovertargetAuthoredID of the sibling popover controlled by the trigger.
sideAuthoredPreferred placement: top, right, bottom, or left.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

The native Popover API owns non-modal disclosure, top-layer rendering, outside pointer dismissal, and Escape closure. popovertarget connects the invoker to the popover element. AngularTS remains responsible for authored content, form values, and application state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use a native button invoker and give the popover content a useful accessible name when its context is not otherwise clear. Escape and pointer light-dismiss are browser behavior; add autofocus only when moving focus into the content is appropriate.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

21 - skeleton

Loading placeholder primitive

Use class="skeleton" on a block element and control its size with normal CSS.

<div
  style="height: 2.5rem; width: 2.5rem; border-radius: 9999px;"
  class="skeleton"
></div>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Skeleton</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    data-example="skeleton-avatar skeleton-card skeleton-demo skeleton-form skeleton-rtl skeleton-table skeleton-text"
  >
    <main aria-label="Skeleton examples">
      <section
        class="skeleton-demo visual-example"
        aria-label="Loading profile preview"
      >
        <output
          id="labeled-skeleton"
          aria-label="Loading avatar"
          aria-hidden="false"
          style="width: 3rem; height: 3rem; border-radius: 9999px"
          class="skeleton"
        ></output>
        <div class="skeleton-lines">
          <div
            id="decorative-skeleton"
            aria-hidden="true"
            style="width: 15.625rem; height: 1rem"
            class="skeleton"
          ></div>
          <div
            aria-hidden="true"
            style="width: 12.5rem; height: 1rem"
            class="skeleton"
          ></div>
        </div>
      </section>

      <section class="skeleton-card-demo" aria-label="Loading card">
        <div class="skeleton-card-media skeleton"></div>
        <div class="skeleton-line-wide skeleton"></div>
        <div class="skeleton-line-medium skeleton"></div>
        <div class="skeleton-button-placeholder skeleton"></div>
      </section>

      <section class="skeleton-form-demo" aria-label="Loading form">
        <div>
          <div class="skeleton-label-placeholder skeleton"></div>
          <div class="skeleton-input-placeholder skeleton"></div>
        </div>
        <div>
          <div class="skeleton-label-placeholder skeleton"></div>
          <div class="skeleton-input-placeholder skeleton"></div>
        </div>
        <div class="skeleton-button-placeholder skeleton"></div>
      </section>

      <section class="skeleton-table-demo" aria-label="Loading table">
        <div class="skeleton-table-heading skeleton"></div>
        <div class="skeleton-table-row">
          <div class="skeleton"></div>
          <div class="skeleton"></div>
          <div class="skeleton"></div>
        </div>
        <div class="skeleton-table-row">
          <div class="skeleton"></div>
          <div class="skeleton"></div>
          <div class="skeleton"></div>
        </div>
        <div class="skeleton-table-row">
          <div class="skeleton"></div>
          <div class="skeleton"></div>
          <div class="skeleton"></div>
        </div>
      </section>

      <section class="skeleton-text-demo" aria-label="Loading text">
        <div class="skeleton-line-wide skeleton"></div>
        <div class="skeleton-line-wide skeleton"></div>
        <div class="skeleton-line-medium skeleton"></div>
      </section>

      <section
        class="skeleton-rtl-demo"
        aria-label="تحميل الملف الشخصي"
        dir="rtl"
        lang="ar"
      >
        <div class="skeleton-avatar-placeholder skeleton"></div>
        <div>
          <div class="skeleton-line-wide skeleton"></div>
          <div class="skeleton-line-medium skeleton"></div>
        </div>
      </section>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Authored loading placeholder.

Anatomy

Root styling selector

  • .skeleton

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

This component has no directive-specific attributes beyond its semantic HTML.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Authored loading placeholder. AngularCSS supplies styling without a runtime directive. Native HTML owns platform behavior; AngularTS owns application values, commands, and authored state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use the appropriate live-region or status semantics for dynamic feedback. Decorative feedback must stay hidden from assistive technology.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

22 - spinner

Loading status indicator

Use class="spinner" on an SVG with an accessible label. Place it in an output when status semantics are needed.

<svg aria-label="Loading" viewBox="0 0 24 24" class="spinner">
  <circle cx="12" cy="12" r="10" />
</svg>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Spinner</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="spinner-demo">
    <div class="visual-example">
      <article variant="muted" class="item">
        <figure>
          <svg
            viewBox="0 0 24 24"
            fill="none"
            aria-live="polite"
            aria-label="Loading"
            aria-busy="true"
            class="spinner"
          >
            <path
              d="M21 12a9 9 0 1 1-6.22-8.56"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
            />
          </svg>
        </figure>
        <section>
          <h3>Processing payment...</h3>
        </section>
        <section class="spinner-amount">
          <span>$100.00</span>
        </section>
      </article>
    </div>
  </body>
</html>

Composition workflows

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Spinner Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    data-example="spinner-badge spinner-button spinner-custom spinner-empty spinner-input-group spinner-rtl spinner-size input-group-spinner"
  >
    <main class="spinner-workflows">
      <div class="workflow-row" aria-label="Spinner sizes">
        <svg
          id="processing-spinner"
          aria-live="assertive"
          aria-label="Processing data"
          style="width: 12px; height: 12px"
          viewBox="0 0 24 24"
          fill="none"
          class="spinner"
        >
          <path
            d="M21 12a9 9 0 1 1-6.22-8.56"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
          />
        </svg>
        <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" class="spinner">
          <path
            d="M21 12a9 9 0 1 1-6.22-8.56"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
          />
        </svg>
        <svg
          aria-hidden="true"
          style="width: 24px; height: 24px"
          viewBox="0 0 24 24"
          fill="none"
          class="spinner"
        >
          <path
            d="M21 12a9 9 0 1 1-6.22-8.56"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
          />
        </svg>
        <svg
          aria-hidden="true"
          style="width: 32px; height: 32px"
          viewBox="0 0 24 24"
          fill="none"
          class="spinner"
        >
          <path
            d="M21 12a9 9 0 1 1-6.22-8.56"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
          />
        </svg>
      </div>

      <div class="workflow-row" aria-label="Spinner badges">
        <span class="badge"
          ><svg
            icon="inline-start"
            viewBox="0 0 24 24"
            fill="none"
            class="spinner"
          >
            <path
              d="M21 12a9 9 0 1 1-6.22-8.56"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
            /></svg
          >Syncing</span
        >
        <span variant="secondary" class="badge"
          ><svg
            icon="inline-start"
            viewBox="0 0 24 24"
            fill="none"
            class="spinner"
          >
            <path
              d="M21 12a9 9 0 1 1-6.22-8.56"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
            /></svg
          >Updating</span
        >
        <span variant="outline" class="badge"
          ><svg
            icon="inline-start"
            viewBox="0 0 24 24"
            fill="none"
            class="spinner"
          >
            <path
              d="M21 12a9 9 0 1 1-6.22-8.56"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
            /></svg
          >Processing</span
        >
      </div>

      <div class="workflow-buttons-column" aria-label="Spinner buttons">
        <button disabled size="sm">
          <svg
            icon="inline-start"
            viewBox="0 0 24 24"
            fill="none"
            class="spinner"
          >
            <path
              d="M21 12a9 9 0 1 1-6.22-8.56"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
            /></svg
          >Loading...
        </button>
        <button variant="outline" disabled size="sm">
          <svg
            icon="inline-start"
            viewBox="0 0 24 24"
            fill="none"
            class="spinner"
          >
            <path
              d="M21 12a9 9 0 1 1-6.22-8.56"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
            /></svg
          >Please wait
        </button>
        <button variant="secondary" disabled size="sm">
          <svg
            icon="inline-start"
            viewBox="0 0 24 24"
            fill="none"
            class="spinner"
          >
            <path
              d="M21 12a9 9 0 1 1-6.22-8.56"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
            /></svg
          >Processing
        </button>
      </div>

      <section class="spinner-empty-demo empty" aria-live="polite">
        <header>
          <figure variant="icon">
            <svg viewBox="0 0 24 24" fill="none" class="spinner">
              <path
                d="M21 12a9 9 0 1 1-6.22-8.56"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
              />
            </svg>
          </figure>
          <h2>Processing your request</h2>
          <p>
            Please wait while we process your request. Do not refresh the page.
          </p>
        </header>
        <section>
          <button variant="outline" size="sm">Cancel</button>
        </section>
      </section>

      <div class="workflow-input-groups" aria-label="Spinner input groups">
        <div class="input-group">
          <input placeholder="Searching..." />
          <div align="inline-end">
            <svg viewBox="0 0 24 24" fill="none" class="spinner">
              <path
                d="M21 12a9 9 0 1 1-6.22-8.56"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
              />
            </svg>
          </div>
        </div>
        <div class="input-group">
          <input placeholder="Saving changes..." />
          <div align="inline-end">
            <span>Saving...</span
            ><svg viewBox="0 0 24 24" fill="none" class="spinner">
              <path
                d="M21 12a9 9 0 1 1-6.22-8.56"
                stroke="currentColor"
                stroke-width="2"
                stroke-linecap="round"
              />
            </svg>
          </div>
        </div>
      </div>

      <article variant="muted" class="spinner-rtl-demo item" dir="rtl">
        <figure>
          <svg viewBox="0 0 24 24" fill="none" class="spinner">
            <path
              d="M21 12a9 9 0 1 1-6.22-8.56"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
            />
          </svg>
        </figure>
        <section>
          <h3>جاري معالجة الدفع...</h3>
        </section>
        <section class="spinner-amount">
          <span>١٠٠.٠٠ دولار</span>
        </section>
      </article>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Authored status indicator.

Anatomy

Root styling selector

  • .spinner

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

AttributeAccessPurpose
sizeAuthoredSpinner size: sm or lg; omit for the default size.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Authored status indicator. AngularCSS supplies styling without a runtime directive. Native HTML owns platform behavior; AngularTS owns application values, commands, and authored state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use the appropriate live-region or status semantics for dynamic feedback. Decorative feedback must stay hidden from assistive technology.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

23 - stepper

Ordered multi-step workflow navigation

Present workflow progress as an ordered list inside navigation. The current step is authored with aria-current="step"; routing and workflow state remain application-owned.

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Stepper</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="stepper-demo">
    <nav class="visual-example" aria-label="Create customer">
      <ol>
        <li><a href="#account">Account</a></li>
        <li><a href="#contacts" aria-current="step">Contacts</a></li>
        <li><span>Permissions</span></li>
        <li><span>Review</span></li>
      </ol>
    </nav>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Native ordered workflow navigation.

Anatomy

Root styling selector

  • nav:has([aria-current="step"])

Semantic structure

Use a native nav containing one direct ordered list. Each item contains a link or text span, and aria-current=step on the current item identifies the Stepper without a class.

API

Attributes and state

AttributeAccessPurpose
aria-currentAuthoredCurrent item or date state.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Stepper styles native ordered navigation and derives completed presentation from the authored current step. AngularTS or routing owns workflow progress and whether a destination is available.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use an ordered list inside a labeled navigation landmark. Apply aria-current=step to exactly one link or text label and do not make unavailable steps interactive.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

24 - toggle

Pressed-state button primitive with aria-pressed state.

Use a native button with authored aria-pressed state. That state identifies the control as a toggle and supplies its styling hook.

<button aria-pressed="true">Bold</button>
<button variant="outline" aria-pressed="false">Italic</button>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Toggle</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="bookmark=false;bold=false;italic=true"
    data-example="toggle-demo toggle-outline toggle-sizes toggle-text"
  >
    <main class="visual-example">
      <div class="row" aria-label="Bookmark toggle">
        <button
          variant="outline"
          size="sm"
          aria-label="Toggle bookmark"
          aria-pressed="{{ bookmark }}"
          ng-click="bookmark = !bookmark"
          type="button"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            aria-hidden="true"
          >
            <path d="M6 3h12v18l-6-4-6 4z" />
          </svg>
          Bookmark
        </button>
      </div>

      <div class="row" aria-label="Text toggles">
        <button
          aria-label="Toggle italic text"
          aria-pressed="{{ italic }}"
          ng-click="italic = !italic"
          type="button"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            aria-hidden="true"
          >
            <path d="M10 4h7M7 20h7M14 4 10 20" />
          </svg>
          Italic
        </button>
      </div>

      <div class="row" aria-label="Outline toggles">
        <button
          variant="outline"
          aria-label="Toggle italic"
          aria-pressed="{{ italic }}"
          ng-click="italic = !italic"
          type="button"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            aria-hidden="true"
          >
            <path d="M10 4h7M7 20h7M14 4 10 20" />
          </svg>
          Italic
        </button>
        <button
          variant="outline"
          aria-label="Toggle bold"
          aria-pressed="{{ bold }}"
          ng-click="bold = !bold"
          type="button"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            aria-hidden="true"
          >
            <path d="M6 4h7a4 4 0 0 1 0 8H6zM6 12h8a4 4 0 0 1 0 8H6z" />
          </svg>
          Bold
        </button>
      </div>

      <div class="row" aria-label="Toggle sizes">
        <button variant="outline" size="sm" type="button" aria-pressed="false">
          Small
        </button>
        <button variant="outline" type="button" aria-pressed="false">
          Default
        </button>
        <button variant="outline" size="lg" type="button" aria-pressed="false">
          Large
        </button>
      </div>

      <output class="output">
        Bookmark: {{ bookmark ? 'on' : 'off' }}, Bold: {{ bold ? 'on' : 'off'
        }}, Italic: {{ italic ? 'on' : 'off' }}
      </output>
    </main>
  </body>
</html>

Workflows

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Toggle Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="disabledState = true; rtlBookmark = false"
    data-example="toggle-disabled toggle-rtl"
  >
    <main class="component-state-grid visual-example">
      <section
        class="component-state-section"
        aria-labelledby="toggle-disabled-heading"
      >
        <h2 id="toggle-disabled-heading">Disabled</h2>
        <div class="row">
          <button
            type="button"
            ng-disabled="disabledState"
            aria-pressed="false"
          >
            Disabled
          </button>
          <button
            type="button"
            variant="outline"
            ng-disabled="disabledState"
            aria-pressed="false"
          >
            Disabled
          </button>
        </div>
        <button
          type="button"
          variant="outline"
          size="sm"
          ng-click="disabledState = !disabledState"
        >
          {{ disabledState ? 'Enable toggles' : 'Disable toggles' }}
        </button>
      </section>

      <section
        class="component-state-section"
        aria-labelledby="toggle-rtl-heading"
        dir="rtl"
        lang="ar"
      >
        <h2 id="toggle-rtl-heading">إشارة مرجعية</h2>
        <button
          type="button"
          size="sm"
          variant="outline"
          aria-label="تبديل الإشارة المرجعية"
          aria-pressed="{{ rtlBookmark }}"
          ng-click="rtlBookmark = !rtlBookmark"
        >
          <svg
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            aria-hidden="true"
          >
            <path d="M6 3h12v18l-6-4-6 4z" />
          </svg>
          إشارة مرجعية
        </button>
        <output class="output">
          الحالة: {{ rtlBookmark ? 'مفعلة' : 'غير مفعلة' }}
        </output>
      </section>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Native button pressed state.

Anatomy

Root styling selector

  • button[aria-pressed]

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

AttributeAccessPurpose
aria-disabledAuthoredSemantic disabled state.
aria-pressedAuthoredPressed state of a toggle control.
sizeAuthoredToggle size: sm or lg; omit for the default size.
variantAuthoredToggle presentation: outline; omit for the default style.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Native button pressed state. AngularCSS supplies styling without a runtime directive. Native HTML owns platform behavior; AngularTS owns application values, commands, and authored state.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use a native button whenever the control performs an action. Keep an accessible name, preserve visible focus, and use disabled for unavailable native controls.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

25 - toggle-group

Native radio or checkbox groups with a toggle-button presentation.

Use radios sharing a name for single selection, or checkboxes for independent multiple selection.

<fieldset variant="outline" class="toggle-group">
  <legend class="visually-hidden">Alignment</legend>
  <label>
    <input type="radio" name="alignment" value="left" ng-model="alignment" />
    Left
  </label>
  <label>
    <input type="radio" name="alignment" value="center" ng-model="alignment" />
    Center
  </label>
</fieldset>

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Toggle Group</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak ng-init="alignment='center'">
    <div class="stack-sm">
      <fieldset class="toggle-group visual-example" variant="outline">
        <legend class="visually-hidden">Text alignment</legend>
        <label>
          <input
            type="radio"
            name="alignment"
            value="left"
            ng-model="alignment"
          />
          Left
        </label>
        <label>
          <input
            type="radio"
            name="alignment"
            value="center"
            ng-model="alignment"
          />
          Center
        </label>
        <label>
          <input
            type="radio"
            name="alignment"
            value="right"
            ng-model="alignment"
          />
          Right
        </label>
      </fieldset>
      <output class="output">
        Alignment: <span ng-bind="alignment"></span>
      </output>
    </div>
  </body>
</html>

Workflows

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Toggle Group Workflows</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body
    ng-app="angular.css"
    ng-cloak
    ng-init="fontWeight='normal'; pageDirection='rtl'; bold=true; italic=true"
    data-example="toggle-group-demo toggle-group-disabled toggle-group-font-weight-selector toggle-group-outline toggle-group-rtl toggle-group-sizes toggle-group-spacing toggle-group-vertical"
  >
    <main class="toggle-group-workflows visual-example">
      <section aria-labelledby="toggle-format-heading">
        <header><h2 id="toggle-format-heading">Formatting</h2></header>
        <fieldset
          class="toggle-group"
          variant="outline"
          id="multiple-toggle-group"
        >
          <legend class="visually-hidden">Text formatting</legend>
          <label><input type="checkbox" ng-model="bold" />Bold</label>
          <label><input type="checkbox" ng-model="italic" />Italic</label>
          <label><input type="checkbox" />Underline</label>
        </fieldset>
      </section>

      <section aria-labelledby="toggle-keyboard-heading">
        <header>
          <h2 id="toggle-keyboard-heading">Keyboard navigation</h2>
        </header>
        <fieldset
          class="toggle-group"
          variant="outline"
          id="keyboard-toggle-group"
        >
          <legend class="visually-hidden">Text style</legend>
          <label
            ><input type="radio" name="style" value="bold" checked />Bold</label
          >
          <label
            ><input
              type="radio"
              name="style"
              value="italic"
              disabled
            />Italic</label
          >
          <label
            ><input
              type="radio"
              name="style"
              value="underline"
            />Underline</label
          >
        </fieldset>
      </section>

      <section aria-labelledby="toggle-disabled-heading">
        <header><h2 id="toggle-disabled-heading">Disabled</h2></header>
        <fieldset class="toggle-group" id="disabled-toggle-group" disabled>
          <legend class="visually-hidden">Disabled formatting</legend>
          <label><input type="checkbox" />Bold</label>
          <label><input type="checkbox" />Italic</label>
          <label><input type="checkbox" />Underline</label>
        </fieldset>
      </section>

      <section aria-labelledby="toggle-weight-heading">
        <header><h2 id="toggle-weight-heading">Font weight</h2></header>
        <fieldset
          class="toggle-group"
          variant="outline"
          spacing="2"
          size="lg"
          id="font-weight-toggle-group"
        >
          <legend class="visually-hidden">Font weight</legend>
          <label class="toggle-weight-item"
            ><input
              type="radio"
              name="weight"
              value="light"
              ng-model="fontWeight"
            /><strong style="font-weight: 300">Aa</strong
            ><span>Light</span></label
          >
          <label class="toggle-weight-item"
            ><input
              type="radio"
              name="weight"
              value="normal"
              ng-model="fontWeight"
            /><strong style="font-weight: 400">Aa</strong
            ><span>Normal</span></label
          >
          <label class="toggle-weight-item"
            ><input
              type="radio"
              name="weight"
              value="medium"
              ng-model="fontWeight"
            /><strong style="font-weight: 500">Aa</strong
            ><span>Medium</span></label
          >
          <label class="toggle-weight-item"
            ><input
              type="radio"
              name="weight"
              value="bold"
              ng-model="fontWeight"
            /><strong style="font-weight: 700">Aa</strong
            ><span>Bold</span></label
          >
        </fieldset>
        <output class="output">Selected: font-{{ fontWeight }}</output>
      </section>

      <section aria-labelledby="toggle-sizes-heading">
        <header><h2 id="toggle-sizes-heading">Sizes and spacing</h2></header>
        <div class="toggle-group-size-stack">
          <fieldset class="toggle-group" size="sm" variant="outline">
            <legend class="visually-hidden">Small position</legend>
            <label
              ><input type="radio" name="small-position" checked />Top</label
            >
            <label><input type="radio" name="small-position" />Bottom</label>
          </fieldset>
          <fieldset
            class="toggle-group"
            variant="outline"
            spacing="2"
            id="spaced-toggle-group"
          >
            <legend class="visually-hidden">Spaced position</legend>
            <label
              ><input type="radio" name="spaced-position" checked />Top</label
            >
            <label><input type="radio" name="spaced-position" />Bottom</label>
          </fieldset>
        </div>
      </section>

      <section aria-labelledby="toggle-vertical-heading">
        <header><h2 id="toggle-vertical-heading">Vertical</h2></header>
        <fieldset
          class="toggle-group"
          orientation="vertical"
          spacing="1"
          id="vertical-toggle-group"
        >
          <legend class="visually-hidden">Vertical formatting</legend>
          <label><input type="checkbox" checked />Bold</label>
          <label><input type="checkbox" checked />Italic</label>
          <label><input type="checkbox" />Underline</label>
        </fieldset>
      </section>

      <section
        dir="{{ pageDirection }}"
        lang="ar"
        id="toggle-rtl-shell"
        aria-labelledby="toggle-rtl-heading"
      >
        <header>
          <h2 id="toggle-rtl-heading">اتجاه العرض</h2>
          <button
            type="button"
            variant="outline"
            size="sm"
            ng-click="pageDirection = pageDirection === 'rtl' ? 'ltr' : 'rtl'"
          >
            Change direction
          </button>
        </header>
        <fieldset class="toggle-group" variant="outline" id="rtl-toggle-group">
          <legend class="visually-hidden">طريقة العرض</legend>
          <label
            ><input type="radio" name="view" value="list" checked />قائمة</label
          >
          <label><input type="radio" name="view" value="grid" />شبكة</label>
          <label><input type="radio" name="view" value="cards" />بطاقات</label>
        </fieldset>
      </section>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Native radio or checkbox grouping.

Anatomy

Root styling selector

  • .toggle-group

Semantic structure

Use semantic HTML with the root styling selector above. Native elements provide the structure; the stylesheet supplies presentation.

API

Attributes and state

AttributeAccessPurpose
orientationAuthoredGroup layout: vertical; omit for the horizontal layout.
sizeAuthoredControl size: sm or lg; omit for the default size.
spacingAuthoredGap in spacing units: 1 or 2; omit to join controls.
variantAuthoredControl presentation: outline; omit for the default style.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

VariablePurpose
--toggle-group-gapGap between controls; defaults to 0.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Toggle Group is a styling-only native fieldset: use radios sharing a name for single selection and checkboxes for multiple selection. The browser owns selection, arrow-key radio navigation, disabled state, focus, validation, and form submission; AngularTS ng-model owns application state. AngularCSS registers no toggle-group directive.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Use a native button whenever the control performs an action. Keep an accessible name, preserve visible focus, and use disabled for unavailable native controls.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.

26 - validation-summary

Linked form validation messages

Place a validation summary before the related fields when submission reveals several errors. Each message links directly to its native form control.

Example

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Validation Summary</title>
    <link rel="stylesheet" href="../../css/preflight.css" />
    <link rel="stylesheet" href="../../css/angular.css" />
    <link rel="stylesheet" href="../example.css" />
    <script src="../../js/angular-ts.umd.js"></script>
    <script src="../../js/angular-css.umd.js"></script>
  </head>
  <body ng-app="angular.css" ng-cloak data-example="validation-summary-demo">
    <main class="visual-example">
      <aside role="alert" tabindex="-1">
        <header>
          <h2>There are two problems with this form</h2>
          <p>Correct the fields below, then submit again.</p>
        </header>
        <ul>
          <li><a href="#customer-name">Enter a customer name.</a></li>
          <li><a href="#customer-email">Enter a valid email address.</a></li>
        </ul>
      </aside>
      <form>
        <label for="customer-name">Customer name</label>
        <input id="customer-name" required />
        <label for="customer-email">Email</label>
        <input id="customer-email" type="email" required />
      </form>
    </main>
  </body>
</html>

Installation

Load the AngularCSS stylesheet. This entry needs no AngularCSS JavaScript or angular.css module dependency. Add AngularTS when using application bindings such as ng-model or ng-click. See Installation for the complete setup.

This entry uses native HTML and CSS. AngularCSS registers no runtime directive for it. Authored validation messages linked to form controls.

Anatomy

Root styling selector

  • aside[role="alert"]:has(> header + ul)

Semantic structure

Use role="alert" on a semantic aside containing a direct header followed by a list of links to invalid controls. No classes or part markers are required.

API

Attributes and state

AttributeAccessPurpose
roleAuthoredExplicit semantic role when native HTML does not provide one.
tabindexAuthoredKeyboard focus order for composite descendants.

Attributes remain authored HTML, native state, or AngularTS inputs. AngularCSS does not write element state.

CSS custom properties

This styling hook does not define component-specific CSS custom properties.

DOM events

This component does not emit a component-specific custom event.

Native DOM events continue to work normally. AngularTS event directives such as ng-click and ng-keydown, plus the data-change model callback, remain application-owned.

Behavior

Validation Summary presents authored error links. Native form validation, AngularTS form controllers, server responses, message visibility, and focus policy remain application-owned.

AngularCSS does not replace AngularTS interpolation, bindings, structural directives, form controllers, validation, or application state.

Accessibility

Give the summary a heading and link every message to its corresponding control. Use an alert or live region when errors appear after submission, then apply application focus policy deliberately.

Authored accessible names and relationships are preserved. Test the final composition with keyboard navigation and assistive technology because labels and content come from the application.

Customization

Target semantic elements, native state selectors, and component classes with ordinary CSS. Behavior and accessible state remain with native HTML and AngularTS; visual choices belong in the application stylesheet.

Read Customization for layer order, design tokens, state variants, and iframe demo isolation.