Skip to content

Popover

Popovers (fw-popover) are visually hidden menus of items activated by a simple button. Use popovers to create complex menus in a visually appealing way.

PropData typeRequired?Description
openBooleanNoControls whether the popover is open. Defaults to false.

Options button

The options button (fw-options-button) is a stylized button you can use to hide and show your popover. Use Vue event handling to map the button to a boolean value.

vue
<script setup lang="ts">
  const open = ref(false)
</script>

<template>
  <fw-popover v-model:open="open">
    <fw-options-button @click="open = !open" />
  </fw-popover>
</template>

You can also use the toggleOpen prop in the <template #default> tag if you prefer not to use refs to control the menu's visibility.

vue
<script setup lang="ts">
const privacyChoices = ['pod', 'public', 'private']
const bcPrivacy = ref('pod')
</script>

<template>
  <fw-popover>
    <template #default="{ toggleOpen }">
      <fw-pill @click.stop="toggleOpen" :blue="bcPrivacy === 'pod'" :red="bcPrivacy === 'public'">
        {{ bcPrivacy }}
      </fw-pill>
    </template>
    <template #items>
      <fw-popover-radio v-model="bcPrivacy" :choices="privacyChoices"/>
    </template>
  </fw-popover>
</template>

Items

Popovers contain a list of menu items. Items can contain different information based on their type.

INFO

Lists of items must be nested inside a <template #items> tag directly under the <fw-popover> tag.

Popover item

The popover item (fw-popover-item) is a simple button that uses Vue event handling. Each item contains a slot which you can use to add a menu label and icon.

vue
<script setup lang="ts">
  const alert = (message: string) => window.alert(message)
  const open = ref(false)
</script>

<template>
  <fw-popover v-model:open="open">
    <fw-options-button @click="open = !open" />
    <template #items>
      <fw-popover-item @click="alert('Report this object?')">
        <i class="bi bi-exclamation" />
        Report
      </fw-popover-item>
    </template>
  </fw-popover>
</template>

Checkbox

The checkbox (fw-popover-checkbox) is an item that acts as a selectable box. Use v-model to bind the checkbox to a boolean value. Each checkbox contains a slot which you can use to add a menu label.

vue
<script setup lang="ts">
const bc = ref(false)
const cc = ref(false)
const open = ref(false)
</script>

<template>
  <fw-popover v-model:open="open">
    <fw-options-button @click="open = !open" />
    <template #items>
      <fw-popover-checkbox v-model="bc">
        Bandcamp
      </fw-popover-checkbox>
      <fw-popover-checkbox v-model="cc">
        Creative commons
      </fw-popover-checkbox>
    </template>
  </fw-popover>
</template>

Radio

The radio (fw-popover-radio) is an item that acts as a radio selector.

PropData typeRequired?Description
modelValueStringYesThe current value of the radio. Use v-model to bind this to a value.
choicesArray<String>YesA list of choices.
vue
<script setup lang="ts">
const open = ref(false);
const currentChoice = ref("pod");
const privacy = ["public", "private", "pod"];
</script>

<template>
  <fw-popover v-model:open="open">
    <fw-options-button @click="open = !open" />
    <template #items>
      <fw-popover-radio v-model="currentChoice" :choices="choices" />
    </template>
  </fw-popover>
</template>

Separator

Use a standard horizontal rule (<hr>) to add visual separators to popover lists.

vue
<script setup lang="ts">
const bc = ref(false)
const cc = ref(false)
const open = ref(false)
</script>

<template>
  <fw-popover v-model:open="open">
    <fw-options-button @click="open = !open" />
    <template #items>
      <fw-popover-checkbox v-model="bc">
        Bandcamp
      </fw-popover-checkbox>
      <hr>
      <fw-popover-checkbox v-model="cc">
        Creative commons
      </fw-popover-checkbox>
    </template>
  </fw-popover>
</template>

To create more complex menus, you can use submenus (fw-popover-submenu). Submenus are menu items which contain other menu items.

vue
<script setup lang="ts">
const bc = ref(false)
const open = ref(false)
</script>

<template>
  <fw-popover v-model:open="open">
    <fw-options-button @click="open = !open" />
    <template #items>
      <fw-popover-submenu>
        <i class="bi bi-collection" />
        Organize and share
        <template #items>
          <fw-popover-checkbox v-model="bc">
            Bandcamp
          </fw-popover-checkbox>
        </template>
      </fw-popover-submenu>
    </template>
  </fw-popover>
</template>

Extra items

You can add extra items to the right hand side of a popover item by nesting them in a <template #after> tag. Use this to add additional menus or buttons to menu items.

vue
<script setup lang="ts">
const bc = ref(false)
const privacyChoices = ['public', 'private', 'pod']
const bcPrivacy = ref('pod')
const open = ref(false)
</script>

<template>
  <fw-popover v-model:open="open">
    <fw-options-button @click="open = !open" />
    <template #items>
      <fw-popover-submenu>
        <i class="bi bi-collection" />
        Organize and share
        <template #items>
          <fw-popover-checkbox v-model="bc">
            Bandcamp
            <template #after>
              <fw-popover>
                <template #default="{ toggleOpen }">
                  <fw-pill @click.stop="toggleOpen" :blue="bcPrivacy === 'pod'" :red="bcPrivacy === 'public'">
                    {{ bcPrivacy }}
                  </fw-pill>
                </template>
                <template #items>
                  <fw-popover-radio v-model="bcPrivacy" :choices="privacyChoices"/>
                </template>
              </fw-popover>
            </template>
          </fw-popover-checkbox>
          <hr>
          <fw-popover-checkbox v-model="share">
            Share by link
            <template #after>
              <fw-button @click.stop="alert('Link copied to clipboard')" color="secondary" round icon="bi-link" />
              <fw-button @click.stop="alert('Here is your code')" color="secondary" round icon="bi-code" />
            </template>
          </fw-popover-checkbox>
        </template>
      </fw-popover-submenu>
    </template>
  </fw-popover>
</template>

Here is an example of a completed menu containing all supported features.

vue
<script setup lang="ts">
const open = ref(false);
const bc = ref(false);
const cc = ref(false);
const share = ref(false);
const bcPrivacy = ref("pod");
const ccPrivacy = ref("public");
const privacyChoices = ["private", "pod", "public"];
</script>

<template>
  <fw-popover v-model:open="open">
    <fw-options-button @click="open = !open" />
    <template #items>
      <fw-popover-item>
        <i class="bi bi-arrow-up-right" />
        Play next
      </fw-popover-item>
      <fw-popover-item>
        <i class="bi bi-arrow-down-right" />
        Append to queue
      </fw-popover-item>
      <fw-popover-submenu>
        <i class="bi bi-music-note-list" />
        Add to playlist
        <template #items>
          <fw-popover-item>
            <i class="bi bi-music-note-list" />
            Sample playlist
          </fw-popover-item>
          <hr />
          <fw-popover-item>
            <i class="bi bi-plus-lg" />
            New playlist
          </fw-popover-item>
        </template>
      </fw-popover-submenu>
      <hr />
      <fw-popover-item>
        <i class="bi bi-heart" />
        Add to favorites
      </fw-popover-item>
      <fw-popover-submenu>
        <i class="bi bi-collection" />
        Organize and share
        <template #items>
          <fw-popover-checkbox v-model="bc">
            Bandcamp
            <template #after>
              <fw-popover>
                <template #default="{ toggleOpen }">
                  <fw-pill
                    @click.stop="toggleOpen"
                    :blue="bcPrivacy === 'pod'"
                    :red="bcPrivacy === 'public'"
                  >
                    {{ bcPrivacy }}
                  </fw-pill>
                </template>
                <template #items>
                  <fw-popover-radio
                    v-model="bcPrivacy"
                    :choices="privacyChoices"
                  />
                </template>
              </fw-popover>
            </template>
          </fw-popover-checkbox>
          <fw-popover-checkbox v-model="cc">
            Creative Commons
            <template #after>
              <fw-popover>
                <template #default="{ toggleOpen }">
                  <fw-pill
                    @click.stop="toggleOpen"
                    :blue="ccPrivacy === 'pod'"
                    :red="ccPrivacy === 'public'"
                  >
                    {{ ccPrivacy }}
                  </fw-pill>
                </template>
                <template #items>
                  <fw-popover-radio
                    v-model="ccPrivacy"
                    :choices="privacyChoices"
                  />
                </template>
              </fw-popover>
            </template>
          </fw-popover-checkbox>
          <hr />
          <fw-popover-item>
            <i class="bi bi-plus-lg" />
            New library
          </fw-popover-item>
          <hr />
          <fw-popover-checkbox v-model="share">
            Share by link
            <template #after>
              <fw-button @click.stop color="secondary" round icon="bi-link" />
              <fw-button @click.stop color="secondary" round icon="bi-code" />
            </template>
          </fw-popover-checkbox>
        </template>
      </fw-popover-submenu>
      <fw-popover-item>
        <i class="bi bi-cloud-download" />
        Download
      </fw-popover-item>
      <hr />
      <fw-popover-item>
        <i class="bi bi-exclamation" />
        Report
      </fw-popover-item>
    </template>
  </fw-popover>
</template>