From ac321364ef046a150125400f08602012c0c937db Mon Sep 17 00:00:00 2001
From: Alejandro Celaya
Date: Thu, 31 Oct 2024 11:13:42 +0100
Subject: [PATCH 1/2] Remove old prototypes which already served their purpose
---
.../FakeAnnotationPublishControl.tsx | 139 ---
.../prototype/LMSContentButtonPage.tsx | 111 ---
.../prototype/LMSContentSelectionPage.tsx | 790 ------------------
.../components/patterns/prototype/Menu.tsx | 258 ------
.../patterns/prototype/MenuArrow.tsx | 32 -
.../patterns/prototype/MenuItem.tsx | 299 -------
.../patterns/prototype/MenuSection.tsx | 44 -
.../prototype/SharedAnnotationsPage.tsx | 312 -------
.../patterns/prototype/TabbedDialogPage.tsx | 322 -------
src/pattern-library/routes.ts | 28 -
10 files changed, 2335 deletions(-)
delete mode 100644 src/pattern-library/components/patterns/prototype/FakeAnnotationPublishControl.tsx
delete mode 100644 src/pattern-library/components/patterns/prototype/LMSContentButtonPage.tsx
delete mode 100644 src/pattern-library/components/patterns/prototype/LMSContentSelectionPage.tsx
delete mode 100644 src/pattern-library/components/patterns/prototype/Menu.tsx
delete mode 100644 src/pattern-library/components/patterns/prototype/MenuArrow.tsx
delete mode 100644 src/pattern-library/components/patterns/prototype/MenuItem.tsx
delete mode 100644 src/pattern-library/components/patterns/prototype/MenuSection.tsx
delete mode 100644 src/pattern-library/components/patterns/prototype/SharedAnnotationsPage.tsx
delete mode 100644 src/pattern-library/components/patterns/prototype/TabbedDialogPage.tsx
diff --git a/src/pattern-library/components/patterns/prototype/FakeAnnotationPublishControl.tsx b/src/pattern-library/components/patterns/prototype/FakeAnnotationPublishControl.tsx
deleted file mode 100644
index 4a83c9bde..000000000
--- a/src/pattern-library/components/patterns/prototype/FakeAnnotationPublishControl.tsx
+++ /dev/null
@@ -1,139 +0,0 @@
-import classnames from 'classnames';
-
-import {
- Button,
- CancelIcon,
- GlobeIcon,
- GroupsIcon,
- InfoIcon,
- LockIcon,
- MenuExpandIcon,
-} from '../../../..';
-import Menu from './Menu';
-import MenuItem from './MenuItem';
-
-export type AnnotationPublishControlProps = {
- /** The group this annotation or draft would publish to */
- group: string;
-
- /**
- * Should the save button be disabled? Hint: it will be if the annotation has
- * no content
- */
- isDisabled?: boolean;
-
- /** Annotation or draft is "Only Me" */
- isPrivate?: boolean;
-
- noSharing?: boolean;
-
- noSharingMessage?: string;
-
- /** Callback for cancel button click */
- onCancel?: () => void;
-
- /** Callback for save button click */
- onSave?: () => void;
-};
-
-/**
- * Render a compound control button for publishing (saving) an annotation:
- * - Save the annotation — left side of button
- * - Choose sharing/privacy option - drop-down menu on right side of button
- *
- * @param {AnnotationPublishControlProps} props
- */
-function AnnotationPublishControl({
- group,
- isDisabled = false,
- isPrivate = false,
- noSharing = false,
- noSharingMessage = "Why can't I share this annotation?",
- onCancel = () => {},
- onSave = () => {},
-}: AnnotationPublishControlProps) {
- const menuLabel = (
-
-
-
- );
-
- return (
-
-
-
- {/* This wrapper div is necessary because of peculiarities with
- Safari: see https://github.com/hypothesis/client/issues/2302 */}
-
-
-
-
-
-
-
-
- );
-}
-
-export default AnnotationPublishControl;
diff --git a/src/pattern-library/components/patterns/prototype/LMSContentButtonPage.tsx b/src/pattern-library/components/patterns/prototype/LMSContentButtonPage.tsx
deleted file mode 100644
index c91f77a89..000000000
--- a/src/pattern-library/components/patterns/prototype/LMSContentButtonPage.tsx
+++ /dev/null
@@ -1,111 +0,0 @@
-import type { ComponentChildren } from 'preact';
-
-import { Card, CardHeader, CardContent, OptionButton } from '../../../../';
-import Library from '../../Library';
-
-/**
- * A relatively simplified layout representation of the LMS content-selection
- * panel
- */
-function ContentPanel({ children }: { children: ComponentChildren }) {
- return (
-
-
-
-
-
-
- Assignment content
-
-
-
Select content for your assignment
-
-
-
-
- {children}
-
-
-
-
-
- );
-}
-
-export default function LMSOptionButtonPage() {
- return (
-
- The new{' '}
-
- OptionButton
- {' '}
- encapsulates a new button design pattern for selecting an option from
- a list of options. The assignment content-configuration screen in LMS
- will use this new button. It is based on a selected design approach in
- the{' '}
-
- set of available sketches
-
- .
-
-
-
-
- NB: There is currently no use of disabled or{' '}
- pressed states in the LMS content-selection interface.
- But the new button provides styling for those states.
-
-
-
-
- You can select content for your assignment from one of
- the following sources:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- It is quick to put the buttons in a two-column grid layout.
- However, because of their heavy, dark color, one ends up with an
- unpleasant optical illusion between button corners.
-
-
-
-
-
-
-
-
- Assignment content
-
-
-
-
- You can select content for your assignment from one of
- the following sources:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Switching buttons from the primary variant to the{' '}
- secondary variant helps the visual artifacts, but
- buttons are hard to scan.
-
-
-
-
-
-
-
-
-
- Assignment content
-
-
-
-
- You can select content for your assignment from one of
- the following sources:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Assignment content
-
-
-
-
- You can select content for your assignment from one of
- the following sources:
-
-
-
- Enter URL of web page or PDF
- Select PDF from Canvas
- Select PDF from Google Drive
- Select JSTOR article
- Select PDF from OneDrive
- Select book from VitalSource
-
-
-
-
-
-
-
-
-
-
-
-
- As a first step, we can shorten the button text and use some
- selective bolding. However, this still feels hard to scan.
-
-
-
-
-
-
-
-
-
- Assignment content
-
-
-
-
- You can select content for your assignment from one of
- the following sources:
-
-
-
-
- URL to web page or PDF
-
-
- PDF from Canvas
-
-
- PDF from Google Drive
-
-
- JSTOR article
-
-
- PDF from OneDrive
-
-
- Book from VitalSource
-
-
-
-
-
-
-
-
-
-
-
-
-
- We can re-arrange the button text for consistency. This is not
- amazing, but may be sensible enough as a starting point.
-
-
-
-
-
-
-
-
-
- Assignment content
-
-
-
-
- You can select content for your assignment from one of
- the following sources:
-
-
-
-
- URL to web page or PDF
-
-
- Canvas PDF
-
-
- Google Drive PDF
-
-
- JSTOR article
-
-
- OneDrive PDF
-
-
- VitalSource book
-
-
-
-
-
-
-
-
-
-
-
-
-
- We can style the content type (e.g. PDF) quieter and aligned
- right.
-
-
-
-
-
-
-
-
-
- Assignment content
-
-
-
-
- You can select content for your assignment from one of
- the following sources:
-
- We can introduce a little subtle color (slate blue), increase
- overall spacing, and tighten up the instructive text. The content
- source name is emphasized and the content types are quieter.
-
- We could add SVG icons to the buttons. Here is shown only
- GoogleDrive, VitalSource and OneDrive as creating SVG icons for
- all of these content sources would take some time. This sketch
- also adds a hover interaction to the buttons.
-
-
-
- Regarding icons: icons in these sketches are
- intended to show how icons might be used. I was able to quickly
- find icons for GoogleDrive and OneDrive and fumble something
- together for VitalSource. We would want to obtain icons for Canvas
- and JSTOR if we moved forward, and adjust icon sizing to be more
- consistent.
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/src/pattern-library/components/patterns/prototype/Menu.tsx b/src/pattern-library/components/patterns/prototype/Menu.tsx
deleted file mode 100644
index 1d8b50fb4..000000000
--- a/src/pattern-library/components/patterns/prototype/Menu.tsx
+++ /dev/null
@@ -1,258 +0,0 @@
-import classnames from 'classnames';
-import type { ComponentChildren } from 'preact';
-import { useCallback, useEffect, useRef, useState } from 'preact/hooks';
-
-import { usePopoverShouldClose } from '../../../../';
-import { MenuExpandIcon } from '../../../../';
-import MenuArrow from './MenuArrow';
-
-/**
- * Flag indicating whether the next click event on the menu's toggle button
- * should be ignored, because the action it would trigger has already been
- * triggered by a preceding "mousedown" event.
- */
-let ignoreNextClick = false;
-
-export type MenuProps = {
- /**
- * Whether the menu content is aligned with the left (default) or right edges
- * of the toggle element.
- */
- align?: 'left' | 'right';
-
- /**
- * Additional CSS class for the arrow caret at the edge of the menu content
- * that "points" toward the menu's toggle button. This can be used to adjust
- * the position of that caret respective to the toggle button.
- */
- arrowClass?: string;
-
- /**
- * Label element or string for the toggle button that hides and shows the menu
- */
- label: ComponentChildren;
-
- /** Menu content, typically `MenuSection` and `MenuItem` components */
- children: ComponentChildren;
-
- /**
- * Whether the menu elements should be positioned relative to the Menu
- * container. When `false`, the consumer is responsible for positioning.
- */
- containerPositioned?: boolean;
-
- /** Additional CSS classes to apply to the Menu */
- contentClass?: string;
-
- /**
- * Whether the menu is open when initially rendered. Ignored if `open` is
- * present.
- */
- defaultOpen?: boolean;
-
- /** Whether to render an (arrow) indicator next to the Menu label */
- menuIndicator?: boolean;
-
- /** Callback when the Menu is opened or closed. */
- onOpenChanged?: (open: boolean) => void;
-
- /**
- * Whether the Menu is currently open, when the Menu is being used as a
- * controlled component. In these cases, an `onOpenChanged` handler should
- * be provided to respond to the user opening or closing the menu.
- */
- open?: boolean;
-
- /**
- * A title for the menu. This is important for accessibility if the menu's
- * toggle button has only an icon as a label.
- */
- title: string;
-};
-
-const noop = () => {};
-
-/**
- * A drop-down menu.
- *
- * Menus consist of a button which toggles whether the menu is open, an
- * an arrow indicating the state of the menu and content when is shown when
- * the menu is open. The children of the menu component are rendered as the
- * content of the menu when open. Typically this consists of a list of
- * `MenuSection` and/or `MenuItem` components.
- *
- * @example
- *
- */
-export default function Menu({
- align = 'left',
- arrowClass = '',
- children,
- containerPositioned = true,
- contentClass,
- defaultOpen = false,
- label,
- open,
- onOpenChanged,
- menuIndicator = true,
- title,
-}: MenuProps) {
- let [isOpen, setOpen]: [boolean, (open: boolean) => void] =
- useState(defaultOpen);
- if (typeof open === 'boolean') {
- isOpen = open;
- setOpen = onOpenChanged || noop;
- }
-
- // Notify parent when menu is opened or closed.
- const wasOpen = useRef(isOpen);
- useEffect(() => {
- if (typeof onOpenChanged === 'function' && wasOpen.current !== isOpen) {
- wasOpen.current = isOpen;
- onOpenChanged(isOpen);
- }
- }, [isOpen, onOpenChanged]);
-
- /**
- * Toggle menu when user presses toggle button. The menu is shown on mouse
- * press for a more responsive/native feel but also handles a click event for
- * activation via other input methods.
- */
- const toggleMenu = (event: Event) => {
- // If the menu was opened on press, don't close it again on the subsequent
- // mouse up ("click") event.
- if (event.type === 'mousedown') {
- ignoreNextClick = true;
- } else if (event.type === 'click' && ignoreNextClick) {
- // Ignore "click" event triggered from the mouse up action.
- ignoreNextClick = false;
- event.stopPropagation();
- event.preventDefault();
- return;
- }
-
- setOpen(!isOpen);
- };
- const closeMenu = useCallback(() => setOpen(false), [setOpen]);
-
- // Set up an effect which adds document-level event handlers when the menu
- // is open and removes them when the menu is closed or removed.
- //
- // These handlers close the menu when the user taps or clicks outside the
- // menu or presses Escape.
- const menuRef = useRef(null);
-
- // Menu element should close via `closeMenu` whenever it's open and there
- // are user interactions outside of it (e.g. clicks) in the document
- usePopoverShouldClose(menuRef, closeMenu, { enabled: isOpen });
-
- const stopPropagation = (e: Event) => e.stopPropagation();
-
- // It should also close if the user presses a key which activates menu items.
- const handleMenuKeyDown = (event: KeyboardEvent) => {
- const key = event.key;
- if (key === 'Enter' || key === ' ') {
- // The browser will not open the link if the link element is removed
- // from within the keypress event that triggers it. Add a little
- // delay to work around that.
- setTimeout(() => {
- closeMenu();
- });
- }
- };
-
- const containerStyle = {
- position: containerPositioned ? 'relative' : 'static',
- };
-
- return (
- // See https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md#case-the-event-handler-is-only-being-used-to-capture-bubbled-events
- // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
-
-
- {isOpen && (
- <>
-
-
- {children}
-
- >
- )}
-
- );
-}
diff --git a/src/pattern-library/components/patterns/prototype/MenuArrow.tsx b/src/pattern-library/components/patterns/prototype/MenuArrow.tsx
deleted file mode 100644
index 4c5e3af25..000000000
--- a/src/pattern-library/components/patterns/prototype/MenuArrow.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import classnames from 'classnames';
-
-import { PointerDownIcon, PointerUpIcon } from '../../../../';
-
-type MenuArrowProps = {
- classes?: string;
- direction?: 'up' | 'down';
-};
-
-/**
- * Render a white-filled "pointer" arrow for use in menus and menu-like
- * elements
- *
- * This will set up absolute positioning for this arrow, but the vertical and
- * horizontal positioning will need to be tuned in the component using the
- * arrow by adding additional utility classes (`classes` prop here).
- */
-export default function MenuArrow({
- classes,
- direction = 'up',
-}: MenuArrowProps) {
- const Icon = direction === 'up' ? PointerUpIcon : PointerDownIcon;
- return (
-
- );
-}
diff --git a/src/pattern-library/components/patterns/prototype/MenuItem.tsx b/src/pattern-library/components/patterns/prototype/MenuItem.tsx
deleted file mode 100644
index bf0a1de4b..000000000
--- a/src/pattern-library/components/patterns/prototype/MenuItem.tsx
+++ /dev/null
@@ -1,299 +0,0 @@
-import classnames from 'classnames';
-import type { ComponentChildren, Ref } from 'preact';
-import { useEffect, useRef } from 'preact/hooks';
-
-import { CaretUpIcon, MenuExpandIcon } from '../../../../';
-import type { IconComponent } from '../../../../';
-
-type SubmenuToggleProps = {
- title: string;
- isExpanded: boolean;
- onToggleSubmenu?: (e: Event) => void;
-};
-
-function SubmenuToggle({
- title,
- isExpanded,
- onToggleSubmenu,
-}: SubmenuToggleProps) {
- // FIXME: Use `MenuCollapseIcon` instead of `CaretUpIcon` once size
- // disparities are addressed
- const Icon = isExpanded ? CaretUpIcon : MenuExpandIcon;
- return (
-
inside of the menu item itself
- // but we have a non-standard mechanism with the toggle control
- // requiring an onClick event nested inside a "menuitemradio|menuitem".
- // Therefore, a static element with a role="none" is necessary here.
- role="none"
- className={classnames(
- // Center content in a 40px square. The entire element is clickable
- 'flex flex-col items-center justify-center w-10 h-10',
- 'text-grey-6 bg-grey-1',
- // Clip the background (color) such that it only shows within the
- // content box, which is a 24px rounded square formed by the large
- // borders
- 'bg-clip-content border-[8px] border-transparent rounded-xl',
- // When the menu item is hovered AND this element is hovered, darken
- // the text color so it is clear that the toggle is the hovered element
- 'group-hover:hover:text-grey-8',
- {
- // When the submenu is expanded, this element always has a darker
- // background color regardless of hover state.
- 'bg-grey-4': isExpanded,
- // When the parent menu item is hovered, it gets a darker background.
- // Make the toggle background darker also.
- 'group-hover:bg-grey-3': !isExpanded,
- },
- )}
- onClick={onToggleSubmenu}
- title={title}
- >
-
-
- );
-}
-
-export type MenuItemProps = {
- /**
- * URL of the external link to open when this item is clicked. Either the
- * `href` or an `onClick` callback should be supplied.
- */
- href?: string;
-
- /**
- * Icon to render for this item. This will show to the left of the item label
- * unless this is a submenu item, in which case it goes on the right. Ignored
- * if this is not a submenu item and `leftChannelContent` is also provided.
- */
- icon?: IconComponent;
-
- /**
- * Dim the label to indicate that this item is not currently available. The
- * `onClick` callback will still be invoked when this item is clicked and the
- * submenu, if any, can still be toggled.
- */
- isDisabled?: boolean;
-
- /** Indicates that the submenu associated with this item is currently open */
- isExpanded?: boolean;
-
- /**
- * Display an indicator to show that this menu item represents something which
- * is currently selected/active/focused.
- */
- isSelected?: boolean;
-
- /**
- * True if this item is part of a submenu, in which case it is rendered with a
- * different style (shaded background)
- */
- isSubmenuItem?: boolean;
-
- /**
- * If present, display a button to toggle the sub-menu associated with this
- * item and indicate the current state; `true` if the submenu is visible.
- * Note. Omit this prop, or set it to null, if there is no `submenu`.
- */
- isSubmenuVisible?: boolean;
-
- label: ComponentChildren;
-
- /**
- * Optional content to render into a left channel. This accommodates small
- * non-icon images or spacing and will supersede any provided icon if this
- * is not a submenu item.
- */
- leftChannelContent?: ComponentChildren;
-
- onClick?: (e: Event) => void;
- onToggleSubmenu?: (e: Event) => void;
- /**
- * Contents of the submenu for this item. This is typically a list of
- * `MenuItem` components with the `isSubmenuItem` prop set to `true`, but can
- * include other content as well. The submenu is only rendered if
- * `isSubmenuVisible` is `true`.
- */
- submenu?: ComponentChildren;
-};
-
-/**
- * An item in a dropdown menu.
- *
- * Dropdown menu items display an icon, a label and can optionally have a submenu
- * associated with them.
- *
- * When clicked, menu items either open an external link, if the `href` prop
- * is provided, or perform a custom action via the `onClick` callback.
- *
- * The icon can either be an external SVG image, referenced by URL, or the
- * name of an icon registered in the application.
- *
- * For items that have submenus, the `MenuItem` will call the `renderSubmenu`
- * prop to render the content of the submenu, when the submenu is visible.
- * Note that the `submenu` is not supported for link (`href`) items.
- */
-export default function MenuItem({
- href,
- icon: Icon,
- isDisabled,
- isExpanded,
- isSelected,
- isSubmenuItem,
- isSubmenuVisible,
- label,
- leftChannelContent,
- onClick,
- onToggleSubmenu,
- submenu,
-}: MenuItemProps) {
- const menuItemRef = useRef(null);
-
- let focusTimer: number | undefined;
-
- // menuItem can be either a link or a button
- let menuItem;
- const hasSubmenuVisible = typeof isSubmenuVisible === 'boolean';
- const isRadioButtonType = typeof isSelected === 'boolean';
-
- useEffect(() => {
- return () => {
- // unmount
- clearTimeout(focusTimer);
- };
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, []);
-
- const onKeyDown = (event: KeyboardEvent) => {
- switch (event.key) {
- case 'ArrowRight':
- if (onToggleSubmenu) {
- event.stopPropagation();
- event.preventDefault();
- onToggleSubmenu(event);
- }
- break;
- case 'Enter':
- case ' ':
- if (onClick) {
- // Let event propagate so the menu closes
- onClick(event);
- }
- }
- };
-
- const renderedIcon = Icon ? : null;
- const leftIcon = !isSubmenuItem ? renderedIcon : null;
- const rightIcon = isSubmenuItem ? renderedIcon : null;
-
- const hasLeftChannel = leftChannelContent || isSubmenuItem || !!leftIcon;
- const hasRightContent = !!rightIcon;
-
- const menuItemContent = (
- <>
- {hasLeftChannel && (
-
- {leftChannelContent ?? leftIcon}
-
- )}
-
- {label}
-
- {hasRightContent && (
-
- {rightIcon}
-
- )}
- {hasSubmenuVisible && (
-
- )}
- >
- );
-
- const wrapperClasses = classnames(
- 'focus-visible-ring ring-inset',
- 'w-full min-w-[150px] flex items-center select-none',
- 'border-b',
- // Set this container as a "group" so that children may style based on its
- // layout state.
- // See https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state
- 'group',
- {
- 'min-h-[30px] font-normal': isSubmenuItem,
- 'min-h-[40px] font-medium': !isSubmenuItem,
- 'bg-grey-1 hover:bg-grey-3': isSubmenuItem || isExpanded,
- 'bg-white hover:bg-grey-1': !isSubmenuItem && !isExpanded && !isDisabled,
- 'bg-grey-0': isDisabled,
- // visual "padding" on the right is part of SubmenuToggle when rendered,
- // but when not rendering a SubmenuToggle, we need to add some padding here
- 'pr-1': !hasSubmenuVisible,
- },
- {
- // When the item is selected, show a left border to indicate it
- 'border-l-[4px] border-l-brand': isSelected,
- // Add equivalent padding to border size when not selected. This instead
- // of a transparent left border to make focus ring cover the full
- // menu item. Otherwise the focus ring will be inset on the left too far.
- 'pl-[4px]': !isSelected,
- 'border-b-grey-3': isExpanded,
- 'border-b-transparent': !isExpanded,
- 'text-color-text-light': isDisabled,
- 'text-color-text': !isDisabled,
- },
- );
-
- if (href) {
- // The menu item is a link
- menuItem = (
- }
- className={wrapperClasses}
- data-testid="menu-item"
- href={href}
- target="_blank"
- tabIndex={-1}
- rel="noopener noreferrer"
- role="menuitem"
- onKeyDown={onKeyDown}
- >
- {menuItemContent}
-
- );
- } else {
- // The menu item is a clickable button or radio button.
- // In either case there may be an optional submenu.
- menuItem = (
-
- );
-}
-
-export default function SharedAnnotationsPrototypePage() {
- return (
-
- Give instructors the ability to create and manage{' '}
- assignment-shared content that all
- assignment participants can see regardless of section group
- membership.
-
- }
- >
-
-
- Note: The UI sketches here are intended as
- low-fidelity wireframes to demonstrate UX and flow intent. They are
- not intended to represent polished design.
-
-
-
- An instructor may create top-level annotations that are visible to
- everyone in the assignment, regardless of which segment they belong
- to. An instructor may edit an annotation and change its sharing
- target.
-
-
-
- A proposed approach is to extend the existing publish-annotation
- interface.
-
-
-
-
-
-
-
-
-
-
-
-
- Content visible to all assignment participants should be{' '}
- {'"merged into" '}
- the annotation threads for the active segment (section/reading group
- as indicated by the group selector in the top bar), but it should be
- easy to distinguish which annotation threads are shared to all
- participants.
-
-
-
- It should be easy to visually distinguish which annotations in the
- sidebar are shared. The treatment shown here is not proposed as a
- design solution.
-
-
-
-
- Annotations
- Page Notes
- Orphans
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Several proposed future features may have some interplay with
- annotation assignment sharing.
-
- }
- >
-
- Note: None of the following features are scoped or
- committed yet. These sketches merely posit some potential UX interplay
- and may be useful as reference later.
-
-
-
- A top-level annotation can be {'"pinned"'} by authorized users,
- which makes the annotation(s) show up at the top of the sidebar
- above the annotation-type tabs at all times. This feature could help
- with the use case of instructors wanting to put certain annotations
- front and center, or provide instructions or prompts for the
- assignment as a whole.{' '}
-
-
-
- As pinning is a toggling function, we could add an additional icon
- to the annotation footer.
-
-
-
-
-
-
-
-
-
-
-
-
An annotation may be both shared and pinned.
-
- Pinned content could be shown above all other content,
- including tabs (i.e. a pinned Page Note would also show up on the
- Annotations tab, but above the tabs). This could satisfy use cases
- relating to creating prompts or instructions for assignments, or
- for otherwise showing certain instructor content at the top.
-
- In the future, we might provide both share/move and copy options
- for a root-level annotation.
-
-
- One option: it might be possible to consolidate some annotation
- actions into a {'"manage-annotation menu"'} at the top right of a
- top-level annotation card.
-