sheet

Edge anchored overlay panels

Use a native dialog and declarative invoker. Author side on the dialog as right, left, top, or bottom; CSS owns only physical placement.

<section class="sheet">
  <button commandfor="profile-sheet" command="show-modal">Open</button>
  <dialog id="profile-sheet" side="right">
    <header>
      <h2>Edit profile</h2>
      <p>Update your account details.</p>
    </header>
    <section>Content</section>
    <footer>
      <button commandfor="profile-sheet" command="close">Close</button>
    </footer>
  </dialog>
</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 Sheet</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="profile={name:'Pedro Duarte',username:'@peduarte'}; savedName='Pedro Duarte'"
    data-example="sheet-demo"
  >
    <main class="visual-example">
      <section id="profile-sheet" class="sheet">
        <button
          commandfor="profile-sheet-content"
          command="show-modal"
          variant="outline"
        >
          Open
        </button>
        <dialog
          id="profile-sheet-content"
          closedby="any"
          aria-labelledby="profile-sheet-title"
          aria-describedby="profile-sheet-description"
          side="right"
        >
          <header>
            <h2 id="profile-sheet-title">Edit profile</h2>
            <p id="profile-sheet-description">
              Make changes to your profile here. Click save when you're done.
            </p>
          </header>
          <form method="dialog">
            <section>
              <label
                ><span>Name</span>
                <input id="sheet-demo-name" ng-model="profile.name" autofocus />
              </label>
              <label
                ><span>Username</span>
                <input id="sheet-demo-username" ng-model="profile.username" />
              </label>
            </section>
            <footer>
              <button
                type="button"
                commandfor="profile-sheet-content"
                command="close"
                ng-click="savedName=profile.name"
              >
                Save changes
              </button>
              <button
                type="button"
                commandfor="profile-sheet-content"
                command="close"
                variant="outline"
              >
                Close
              </button>
            </footer>
          </form>
          <button
            type="button"
            commandfor="profile-sheet-content"
            command="close"
            variant="ghost"
            size="icon-sm"
          >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              aria-hidden="true"
            >
              <path d="M18 6 6 18"></path>
              <path d="m6 6 12 12"></path>
            </svg>
            <span class="visually-hidden">Close sheet</span>
          </button>
        </dialog>
      </section>
      <output class="sheet-output" aria-live="polite">
        Saved profile: <span ng-bind="savedName"></span>
      </output>
    </main>
  </body>
</html>

The example keeps profile values and save state in AngularTS. Sheet owns only modal disclosure, semantics, focus, and placement.

Without Corner Close

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Sheet No Close</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="sheet-no-close-button">
    <main class="visual-example">
      <section id="plain-sheet" class="sheet">
        <button
          variant="outline"
          type="button"
          commandfor="plain-sheet-content"
          command="show-modal"
        >
          Open Sheet
        </button>
        <dialog
          id="plain-sheet-content"
          closedby="any"
          aria-labelledby="plain-sheet-title"
          aria-describedby="plain-sheet-description"
          side="right"
        >
          <header>
            <h2 id="plain-sheet-title">No Close Button</h2>
            <p id="plain-sheet-description">
              This sheet doesn't have a close button in the top-right corner.
              Click outside to close.
            </p>
          </header>
        </dialog>
      </section>
    </main>
  </body>
</html>

The panel intentionally omits close controls and remains dismissible through the exact overlay or Escape.

Sides

View source
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>AngularCSS Sheet Sides</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="paragraphs=[1,2,3,4,5,6,7,8,9,10]"
    data-example="sheet-side"
  >
    <main class="sheet-sides-demo visual-example">
      <section side="top" class="sheet">
        <button
          variant="outline"
          type="button"
          commandfor="sheet-native-624-content"
          command="show-modal"
        >
          Top
        </button>
        <dialog
          size="half"
          id="sheet-native-624-content"
          closedby="any"
          aria-labelledby="sheet-native-624-title"
          aria-describedby="sheet-native-624-description"
          side="top"
        >
          <header>
            <h2 id="sheet-native-624-title">Edit profile</h2>
            <p id="sheet-native-624-description">
              Make changes to your profile here. Click save when you're done.
            </p>
          </header>
          <section class="sheet-side-copy">
            <p ng-repeat="item in paragraphs">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris.
            </p>
          </section>
          <footer>
            <button>Save changes</button>
            <button
              variant="outline"
              commandfor="sheet-native-624-content"
              command="close"
            >
              Cancel
            </button>
          </footer>
        </dialog>
      </section>
      <section side="right" class="sheet">
        <button
          variant="outline"
          type="button"
          commandfor="sheet-native-1974-content"
          command="show-modal"
        >
          Right
        </button>
        <dialog
          id="sheet-native-1974-content"
          closedby="any"
          aria-labelledby="sheet-native-1974-title"
          aria-describedby="sheet-native-1974-description"
          side="right"
        >
          <header>
            <h2 id="sheet-native-1974-title">Edit profile</h2>
            <p id="sheet-native-1974-description">
              Make changes to your profile here. Click save when you're done.
            </p>
          </header>
          <section class="sheet-side-copy">
            <p ng-repeat="item in paragraphs">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris.
            </p>
          </section>
          <footer>
            <button>Save changes</button>
            <button
              variant="outline"
              commandfor="sheet-native-1974-content"
              command="close"
            >
              Cancel
            </button>
          </footer>
        </dialog>
      </section>
      <section side="bottom" class="sheet">
        <button
          variant="outline"
          type="button"
          commandfor="sheet-native-3320-content"
          command="show-modal"
        >
          Bottom
        </button>
        <dialog
          size="half"
          id="sheet-native-3320-content"
          closedby="any"
          aria-labelledby="sheet-native-3320-title"
          aria-describedby="sheet-native-3320-description"
          side="bottom"
        >
          <header>
            <h2 id="sheet-native-3320-title">Edit profile</h2>
            <p id="sheet-native-3320-description">
              Make changes to your profile here. Click save when you're done.
            </p>
          </header>
          <section class="sheet-side-copy">
            <p ng-repeat="item in paragraphs">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris.
            </p>
          </section>
          <footer>
            <button>Save changes</button>
            <button
              variant="outline"
              commandfor="sheet-native-3320-content"
              command="close"
            >
              Cancel
            </button>
          </footer>
        </dialog>
      </section>
      <section side="left" class="sheet">
        <button
          variant="outline"
          type="button"
          commandfor="sheet-native-4686-content"
          command="show-modal"
        >
          Left
        </button>
        <dialog
          id="sheet-native-4686-content"
          closedby="any"
          aria-labelledby="sheet-native-4686-title"
          aria-describedby="sheet-native-4686-description"
          side="left"
        >
          <header>
            <h2 id="sheet-native-4686-title">Edit profile</h2>
            <p id="sheet-native-4686-description">
              Make changes to your profile here. Click save when you're done.
            </p>
          </header>
          <section class="sheet-side-copy">
            <p ng-repeat="item in paragraphs">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
              enim ad minim veniam, quis nostrud exercitation ullamco laboris.
            </p>
          </section>
          <footer>
            <button>Save changes</button>
            <button
              variant="outline"
              commandfor="sheet-native-4686-content"
              command="close"
            >
              Cancel
            </button>
          </footer>
        </dialog>
      </section>
    </main>
  </body>
</html>

Top and bottom panels use a half-viewport maximum in this composition. The scrolling body remains independent from the header and footer.

RTL

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 Sheet 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="profile={name:'Pedro Duarte',username:'peduarte'}; savedName='Pedro Duarte'"
    data-example="sheet-rtl"
  >
    <main class="visual-example">
      <section id="rtl-profile-sheet" side="left" class="sheet">
        <button
          variant="outline"
          type="button"
          commandfor="rtl-profile-sheet-content"
          command="show-modal"
        >
          فتح
        </button>
        <dialog
          id="rtl-profile-sheet-content"
          closedby="any"
          aria-labelledby="rtl-profile-sheet-title"
          aria-describedby="rtl-profile-sheet-description"
          side="left"
        >
          <header>
            <h2 id="rtl-profile-sheet-title">تعديل الملف الشخصي</h2>
            <p id="rtl-profile-sheet-description">
              قم بإجراء تغييرات على ملفك الشخصي هنا. انقر حفظ عند الانتهاء.
            </p>
          </header>
          <form method="dialog">
            <section>
              <label
                ><span>الاسم</span>
                <input id="sheet-rtl-name" ng-model="profile.name" autofocus />
              </label>
              <label
                ><span>اسم المستخدم</span>
                <input id="sheet-rtl-username" ng-model="profile.username" />
              </label>
            </section>
            <footer>
              <button
                type="button"
                ng-click="savedName=profile.name"
                commandfor="rtl-profile-sheet-content"
                command="close"
              >
                حفظ التغييرات
              </button>
              <button
                type="button"
                variant="outline"
                commandfor="rtl-profile-sheet-content"
                command="close"
              >
                إغلاق
              </button>
            </footer>
          </form>
          <button
            variant="ghost"
            size="icon-sm"
            commandfor="rtl-profile-sheet-content"
            command="close"
          >
            <svg
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              aria-hidden="true"
            >
              <path d="M18 6 6 18"></path>
              <path d="m6 6 12 12"></path>
            </svg>
            <span class="visually-hidden">إغلاق اللوحة</span>
          </button>
        </dialog>
      </section>
      <output class="sheet-output" aria-live="polite">
        الملف المحفوظ: <span ng-bind="savedName"></span>
      </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. A native dialog presented as a side sheet.

Anatomy

Root styling selector

  • .sheet

Semantic structure

Use .sheet as a wrapper containing a native invoker button and dialog with authored side. Close controls use command=close; semantic headers, sections, forms, and footers need no anatomy classes.

API

Attributes and state

AttributeAccessPurpose
commandAuthoredNative invoker action such as show-modal or close.
dirAuthoredText and interaction direction: ltr or rtl.
sideAuthoredDialog edge: top, right, bottom, or left.
sizeAuthoredUse half for a half-height top or bottom sheet.

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

A native dialog owns modal disclosure, focus, Escape, background isolation, and restoration. The concise authored side attribute selects CSS edge placement. AngularTS remains responsible for form values, validation, submission, language, and authored content.

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

Accessibility

Use a visible title and description connected to the native dialog. Keep the physical edge as presentation only; content order, focus order, and inherited text direction remain semantic.

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.