@jaaahn/hyper-ui

3.1.1 • Public • Published

HyperUI

Welcome to HyperUI, a personal Vue 3 component library fitting my needs.

HyperUI aims on being an easy to use, opinionated component library for Vue 3. It provides components and the necessary building blocks to design web apps, but unlike other libraries does not provide excessive customizability. HyperUI supports automatic darkmode based on the users system preferences.

As this library is a personal project, it does not come with a lot of customization options, but in this documentation there are some tips on how to customize the design using CSS. If you think like there is something off with your design, then feel encouraged to use CSS to tweak it the way you like it.

Licensed under MIT License.

Attention Breaking Changes

Upgrading to Version 3.0.0:

We refined the naming scheme of this library. Please search your codebase for these classes and replace them with:

OLD NEW
reset --> hy-reset
--font-color-similar --> --font-color-match
same --> match (only affects HyPopover, HyPopoverFree, HySmartMenu and HySmartMenuFree)

We also changed targeting classes and utility classes to fit this new naming scheme. We strongly incourage you to use the new syntax. With this syntax, every class now matches its corresponding component name:

OLD NEW
hyper-button --> hy-button
hyper-checkbox --> hy-checkbox
hyper-dropzone --> hy-dropzone
hyper-flexcontainer --> hy-flex-container
hyper-header --> hy-header
hyper-input --> hy-input
hyper-listicon --> hy-list-icon
hyper-loader --> hy-loader
hyper-main --> hy-main
hyper-modal --> hy-modal
hyper-navigationcontainer --> hy-navigation-container
hyper-navigationsidebar --> hy-navigation-sidebar
hyper-navigationtabbar --> hy-navigation-tabbar
hyper-popover --> hy-popover
hyper-popoverfree --> hy-popover-free
hyper-progressbar --> hy-progress-bar
hyper-radiobutton --> hy-radio-button
hyper-section --> hy-section
hyper-select --> hy-select
hyper-smartmenu --> hy-smart-menu
hyper-smartmenufree --> hy-smart-menu-free
hyper-subsection --> hy-sub-section
hyper-tabbar --> hy-tabbar
hyper-table --> hy-table
hyper-textarea --> hy-text-area
hyper-toggle --> hy-toggle

Upgrading to Version 2.0.0:

  • New component naming scheme -> Please refer to the component documentation
  • Styles now need to be imported manually -> Please refer to the Import Section

Content

Install and import

1. Installing the library

Via NPM

npm install @jaaahn/hyper-ui

2. Importing the library

// Standard Vue Code
import { createApp } from "vue";
import App from "./App.vue";

const app = createApp(App);
// Standard Vue Code above
// #######################

// See below for config options; these can be omitted
let config = {
    theme: "system",
    size: "normal",
};

import HyperUI from "@jaaahn/hyper-ui";
app.use(HyperUI, config); // config is optional and can be omitted

import "@jaaahn/hyper-ui/styles"; // Import styles

// #######################
// Standard Vue Code below
app.mount("#app");

This is all you need. Now you can use these components within your template. You don't need to import them in each file and you also don't need to put them within you components object in your Vue instance as you would do it with your own custom components.

3. Config

HyperUI allows you to change its behaviour by providing a config.
This config is a JS object passed to the app.use(...) function as the second argument (see above). But, passing this is completely optional and the config can just be omitted if one does not want to change the libraries behaviour.

Config options

Name  Type Default Possible values Extra info
theme String "system" "system", "light" or "dark" system will choose light- or darkmode depending on the users system preferences
size String "normal" "normal", "light" or "thin" Only on supported elements

4. Preparing your HTML file

If you are planning on using the included HyHeader component, please add these theme-color meta tags to your html head:

<meta name="theme-color" content="#fff" media="(prefers-color-scheme: light)" />

<meta name="theme-color" content="hsl(220, 5%, 13%)" media="(prefers-color-scheme: dark)" />

If you are NOT planning on using the Header, then add the following to your html head:

<meta name="theme-color" content="#eeeef2" media="(prefers-color-scheme: light)" />

<meta name="theme-color" content="#000" media="(prefers-color-scheme: dark)" />

Component Documentation

Component names can be written in Camel Case with the first letter also capitalized, like "HyFlexContainer" or "HyButton". Alternatively you can also write the components in lowercase syntax like "hy-flex-container" or "hy-button".

Mind you: If passing a non string to a prop, you need to use v-bind:PROPNAME. Otherwise you will get a warning in your console.

HyButton

Basic <button> element. It comes in two colors, can be disabled and put into a loading state.

Targeting class

hy-button

Slot

Pass a slot which will be displayed as the normal <button> text.

Options

Name  Type Default  Extra info
type String "secondary" See down below
size String normal Size Option Docs
loading Boolean false For spinner: leave progress = null. For progress bar: provide a progress value between 0-1
disabled Boolean false
extend Boolean true Controls wether the element extends to 100% or stays at max-content. Not recommended, use .hy-extend-full instead.
progress Number null Range between 0-1. Values not in this range will be caped
progressWidth String min(70%, 150px) Specify a width (valid css)

Different styles or types

Option name Result
primary Primary action button style featuring the blue accent color
secondary Secondary action button, matches the background color
transparent Button with only text. Has hover and click effect. 
transparent-bg Button with text and a slightly visible gray background. Has hover and click effect. 
light-blue Compare to above 
light-bg-blue Compare to above 
light-red Compare to above 
light-bg-red Compare to above 
light-orange Compare to above 
light-bg-orange Compare to above 
light-green Compare to above 
light-bg-green Compare to above 

Example

<!-- Loading with spinner -->
<hy-button @click="method('hello')" :disabled="false" :loading="isLoading" type="primary">
    Click me
</hy-button>

<!-- Loading with progress -->
<hy-button @click="method('hello')" :disabled="false" :loading="isLoading" :progress="loadingProgress" type="primary">
    Click me
</hy-button>

Notice: Target a specific style of button

Every HyButton component is a <button> nested inside a <div> element (see Re-Styling Components). The specific styles (controlled by the type option) are applied to the <button> element by a class, which matches the type's name. So, if you want to change the background-color of every transparent button, you could use something like:

.hy-button :deep(button.transparent) {
    background-color: yellow !important;
}

/* :deep() is explained in the "Re-Style Components" section */

HyInput

Basic <input> element. It can be disabled and put into an loading state.
Use v-model to create a two-way binding.

Targeting class

hy-input

v-model

Syncs the current input value with your parent vue instance. View the Info about v-model section for more details.

Slot

This component can hold up to 2 icons. One on the left and one on the right.
By default, passing an icon into the slot will position it left to the text. If you want the icon to appear at the right of the input component, then use a named slot with the name right. If you want to display two icons simultaneously, then use two named slots using the names left and right.
This feature was build to work with icon-fonts using the <i> tag. Other systems may also work, but may require more tweaking. Your icons should have a width of around 20px.
These icons cannot be clicked on.

Options

Name  Type Default  Extra info
modelValue any - Required. Two-way binding for the input's value
type String "text" Equal to HTML's type attribute. E.g. type="password"
size String normal Size Option Docs
placeholder String ""
loading Boolean false For spinner: leave progress = null. For progress bar: provide a progress value between 0-1
disabled Boolean false
extend Boolean true Controls wether the element extends to 100% or stays at max-content. Not recommended, use .hy-extend-full instead.
required Boolean false Equal to HTML's required attribute.
progress Number null Range between 0-1. Values not in this range will be caped
progressWidth String min(70%, 150px) Specify a width (valid css)

NOTE: Inheriting Props

The option autocomplete got removed in favor of vue's $attrs.
All HTML props except id, class and vue props listed above, will be inherited to the underlying <input> element.
Vue will also automatically inherit all props, including id and class, to the <div> wrapper that this component uses.

Example

<hy-input v-model="username" :disabled="false" :loading="isLoading" type="text" placeholder="Your username"></hy-input>

With an Icon on the left side

<hy-input v-model="username" :disabled="false" :loading="isLoading" type="text" placeholder="Your username">
    <i class="icon-search"></i>
</hy-input>

With an Icon on the right side

<hy-input v-model="username" :disabled="false" :loading="isLoading" type="text" placeholder="Your username">
    <template #right>
        <i class="icon-megaphone"></i>
    </template>
</hy-input>

With an Icon on the left and on the right side

<hy-input v-model="username" :disabled="false" :loading="isLoading" type="text" placeholder="Your username">
    <template #left>
        <i class="icon-search"></i>
    </template>
    <template #right>
        <i class="icon-megaphone"></i>
    </template>
</hy-input>

With progress bar

<hy-input v-model="username" :disabled="false" :loading="isLoading" :progress="loadingProgress" type="text" placeholder="Your username"></hy-input>

HyTextArea

Basic <textarea> element with the option of being disabled.
Use v-model to create a two-way binding.
This Component was not build for being used within a FlexContainer.

Targeting class

hy-text-area

v-model

Syncs the current input value with your parent vue instance. View the Info about v-model section for more details.

Options

Name  Type Default  Extra info
modelValue String - Required. Two-way binding for the input's value
placeholder String  ""
disabled Boolean false
required Boolean false Equal to HTML's required attribute.
resize String vertical Equal to CSS resize rule. Correct values are none, both, vertical & horizontal
size String normal Size Option Docs

NOTE: Inheriting Props

All HTML props except id, class and vue props listed above, will be inherited to the underlying <textarea> element.
Vue will also automatically inherit all props, including id and class, to the <div> wrapper that this component uses.

Example

<hy-text-area v-model="essay" :disabled="false"  placeholder="Your essay goes here" />

HySelect

A HTML select element with custom styling and an icon. Use v-model to create a two-way binding.

Targeting class

hy-select

v-model

Syncs the selected option with your parent vue instance. View the Info about v-model section for more details. This allows you to programmatically set the value while still allowing the user to select the option he wants.

Slot

Pass the <option> elements as you would with regular HTML.

If you want to display an icon on the left side of the component, then you need to use named slots:
One named slot for the options and one for the icon.
Ref example for more detail.

This feature was build to work with icon-fonts using the <i> tag. Other systems may also work, but may require more tweaking. Your icons should have a width of around 20px.
These icons cannot be clicked on.

Options

Name  Type Default  Extra info
modelValue String - Required. Two-way binding about the selected option
loading Boolean false For spinner: leave progress = null. For progress bar: provide a progress value between 0-1
disabled Boolean false
extend Boolean true Controls wether the element extends to 100% or stays at max-content. Not recommended, use .hy-extend-full instead.
size String normal Size Option Docs
progress Number null Range between 0-1. Values not in this range will be caped
progressWidth String min(70%, 150px) Specify a width (valid css)

Example

<hy-select v-model="variable" :disabled="false" :loading="isLoading">
    <option value="option1">Option 1</option>
    <option value="option2">Option 2</option>
</hy-select>

With an icon:

<hy-select v-model="variable" :disabled="false" :loading="isLoading">
    <template #options>
        <option value="option1">Option 1</option>
        <option value="option2">Option 2</option>
    </template>

    <template #icon>
        <i class="icon-sort-descending"></i>
    </template>
</hy-select>

With progress bar

<hy-select v-model="variable" :disabled="false" :loading="isLoading" :progress="loadingProgress">
    <option value="option1">Option 1</option>
    <option value="option2">Option 2</option>
</hy-select>

HyCheckbox

Standard checkbox. It can be disabled. Use v-model to create a two-way binding.

Targeting class

hy-checkbox

v-model

Syncs whether the box is ticked or not with your parent vue instance. View the Info about v-model section for more details.

Slot

Use the slot to pass text which will be displayed as a label.

Options

Name  Type Default  Extra info
modelValue Boolean - Required. Two-way binding for the checkbox's value
disabled Boolean false
extend Boolean true Controls wether the element extends to 100% or stays at max-content. Not recommended, use .hy-extend-full instead.
type String left left or right. Aligns either label and box left, or label on the left and box on the right

Example

<hy-checkbox v-model="someBooleanVariable" :disabled="disabledVariable" type="right">
    Click me
</hy-checkbox>

HyToggle

An iOS style toggle "checkbox". Sometimes this is also called a "switch".

This component is functionally identical to the <hy-checkbox> component. Please refer to its documentation.

Example

<hy-toggle v-model="someBooleanVariable" :disabled="disabledVariable" type="right">
    Toggle me
</hy-toggle>

HyRadioButton

Standard radio button. It can be disabled. Use v-model to create a two-way binding.

Targeting class

hy-radio-button

v-model

Syncs which radio button is selected with your parent vue instance. View the Info about v-model section for more details. This allows you to programmatically set the value while still allowing the user to select the option he wants.

Slot

Use the slot to pass text which will be displayed as a label.

Options

Name  Type Default Required Extra info
modelValue String - Required Two-way binding about wether the radio is selected or not.
value String - Required Value of your radio button. If the radio button is clicked, this will be written to your modelValue variable. Works similar to html's <option value="...">-tag one uses within selects.
name String - - Set the name attribute of the <input type="radio">-tag used within the component.
disabled Boolean false -
type String left - Set to left or right. Aligns either label and box left, or label on the left and box on the right.
extend Boolean true - Controls wether the element extends to 100% or stays at max-content. Not recommended, use .hy-extend-full instead.

Example

<!-- These three components will form a radio group, where only one option can be selected at a time. --> 
<hy-radio-button v-model="someVariable" value="option1" :disabled="disabledVariable"> Option 1 </hy-radio-button>  
<hy-radio-button v-model="someVariable" value="option2" :disabled="disabledVariable"> Option 2 </hy-radio-button>  
<hy-radio-button v-model="someVariable" value="option3" :disabled="disabledVariable" type="right"> Option 3 </hy-radio-button>

HyDropzone

A dropzone component. Drop a file or click on it to open a native file selector window.

Targeting class

hy-dropzone

Options

Name Type Default Required Extra info
placeholder String "Drop file here or click to select a file" -
readMode String "text" - How the file will be read. Choose between text, binaryString, dataURL or arrayBuffer. More info about what they do
accept String * - Which files to accept. About this attribute and how its syntax works

Reading the selected file

Once the user selects a file, the newValue event will be fired with an event object containing the following information:

{
    content: String,
    name: String,
    size: Number,
    lastModified: Number,
    type: String // MIME-Type of the selected file
}

Clearing the selected file

If one wants to clear the selected file, please call the clear method on the component instance. If this method is called, the newValue event will fire with $event = null.
Guide on how to do this using Vue refs:

<hy-dropzone readMode="dataURL" accept="image/*" @newValue="my_method_for_handling_the_event($event)" ref="myDropzone" />

<hy-button @click="$refs.myDropzone.clear()"> Clear </hy-button>

Directly accessing the underlying <input> element

The underlying <input type="file"> html element is the second child node of the dropzone component. Thus is can be direcly referenced:

<hy-dropzone ref="myDropzone" />
let inputElement = this.$refs.myDropzone.$el.childNodes[1];

Example

Hint: In Vue, the $event is the variable that contains the event object of the triggered event.

<hy-dropzone readMode="text" accept="text/*,application/*,.md" @newValue="myVariable = $event" /> 

Or:

<hy-dropzone readMode="dataURL" accept="image/*" @newValue="my_method_for_handling_the_event" /> 

Or:

<hy-dropzone readMode="dataURL" accept="image/*" @newValue="my_method_for_handling_the_event($event)" /> 

HyTabbar

A tabbar with multiple tabs the user can switch between. Sometimes this is known as a segmented picker or a switch. Use v-model to create a two-way binding, much like the <Select> works.
This component supports dynamically created options (e.g. if using a v-for loop for generating options).
If there are too many options to fit them, the component will automatically allow the user to scroll through the options. For this to work, the component may not be wrapped in a display: flex container or a hy-flex-container!

Targeting class

hy-tabbar

v-model

Syncs the selected tab with your parent vue instance. View the Info about v-model section for more details.

Slot

Syntax: <p data-value="valueOfTab"> Bla bla bla </p>.
See the example below for more info on how to use this element.
Why? Due to technical restrictions, you can't just simply use a <option value=""> element in the slot. Instead, please use a <p> with a custom data-attribute called data-value, like data-value="tab1" or data-value="optionA". You are going to run into issues if this attribute is not given on an option element.

Options

Name  Type Default  Extra info
modelValue String Required. Two-way binding about which tab is selected
disabled Boolean false

Example

<hy-tabbar v-model="variable" :disabled="disabledVariable">
    <p data-value="tab1">Tab 1</p>
    <p data-value="tab2">Tab 2</p>
    <p data-value="tab3">Tab 3</p>
</hy-tabbar>

HyLoader

This is a custom loading indicator.
Use v-if="booleanVariable" to show the indicator or not.
This is just a spinning wheel, you must position the indicator by yourself.

Targeting class

hy-loader

Options

Name  Type Default  Extra info
width Number 25 In css px
height Number 25 In css px
line Number 5 In css px. This is how thick the line is rendered

Example

<hy-loader v-if="isLoading" :width="25" :height="25" :line="3" />

HyProgressBar

This is a custom progress bar.

Targeting class

hy-progress-bar

Options

Name  Type Default  Extra info
progress Number - Required. Range between 0-1. Values not in this range will be caped
width String "100%" Specify a width (valid css)

Example

<hy-progress-bar  v-if="isLoading" :progress="loadingProgress" width="50%" />

HyFlexContainer

This is basically a div with display: flex applied to it. If the screen is smaller than 800px, the flex-direction will be set to column

Targeting class

hy-flex-container

Slot

Pass the elements you want to position within the FlexContainer via the slot.

Options

Name  Type Default  Extra info
wrap Boolean true Controls the css flex-wrap property, switches between wrap and no-wrap
justify String space-between Controls the css justify-content property
verticalAlign String center Controls the css align-items property
direction String row Controls the css flex-direction property
allowBreak Boolean true Wether the flex-container should switch to flex-direction: column if the screen is smaller than 800px

Your items will shrink to the minimum width without shrinking your content (e.g. text). If you would like to change this behaviour, please do this manually in your css.

Example

<hy-flex-container>
    <input />
    <button>Hello</button>
    <hy-checkbox />
</hy-flex-container>

HySection

This is a section, with (unlike the body) a white background. It should be used most of the time when working with content. A section includes a title and two description fields.

Targeting class

hy-section

Slot

Pass the elements you want to position within the Section via the slot.

v-model: Make it collapsable

If provided alongside a value for title, the section becomes collapsable. Omit this, if you don't want the section to be collapsable (default behaviour).
View the Info about v-model section for more details.

Options

Any title, pre or post field left as null won't be rendered.

Name  Type Default  Extra info
border Boolean false
divider Boolean false A divider between each element will be added automatically if set to true
title String null
pre String null Description field over slot
post String null Description field under slot
modelValue Boolean null Collapse the section (only active, if a value for title is provided)

Example

<hy-section :border="true" :divider="false">
    <hy-flex-container>
        <input />
        <hy-button>Hello</hy-button>
        <hy-checkbox />
    </hy-flex-container>
</hy-section>

<hy-section title="My Section" pre="Description" v-model="testSectionCollapsed">
    <hy-button>Hello</hy-button>
</hy-section>

HySubSection

Has a slightly darker background-color than a section. Intended for use with only one input / button (etc.) element but one can pass any element via the slot. A sub-section includes a title and two description fields.

Targeting class

hy-sub-section

Slot

Pass the element(s) you want to position within the Sub-Section via the slot.

v-model: Make it collapsable

If provided alongside a value for title, the sub-section becomes collapsable. Omit this, if you don't want the section to be collapsable (default behaviour).
View the Info about v-model section for more details.

Options

Any title, pre or post field left as null won't be rendered.

Name  Type Default  Extra info
title String null
pre String null Description field over slot
post String null Description field under slot
modelValue Boolean null Collapse the sub-section (only active, if a value for title is provided)

Example

<hy-sub-section title="Title" pre="First description" post="Second description">
    <hy-input v-model="testInput" placeholder="Input field" />
</hy-sub-section>

<hy-sub-section title="Title" v-model="testSubSectionCollapsed">
    <hy-input v-model="testInput" placeholder="Input field" />
</hy-sub-section>

Info about background color and padding

This component was designed to be used within a regular Section. That's why it has a slightly different color than normal sections. If you want them to appear with the same color as Sections, for example to use them without a wrapper section, then please add the following lines of css to your code:

.hy-sub-section {
    background-color: var(--section-bg-color);

    /* If you want them to have the same padding as regular sections */
    padding: var(--section-padding);
}

HyTable

A table.

Targeting class

hy-table

Slot

Pass HTML table elements.

Options

Name  Type Default  Extra info
border Boolean true

Example

<hy-table :border="true">
    <tr>
        <th>Col 1</th>
        <th>Col 2</th>
    </tr>
    <tr>
        <td>Hello</td>
        <td>World</td>
    </tr>
</hy-table>

HyMain

A container that resizes based on your screen size. At a certain screen size it locks to a width of 1400px (or whatever you specify it to).

Targeting class

hy-main

Slot

Pass the elements you want to position within the Main view via the slot.

Options

Name  Type Default  Extra info
maxWidth String "1400px" Desired css max-width value
resizeTo Number 95 Will be a max-width in percent that the container will resize to if it must be smaller than the given maxWidth
usingHyHeader Boolean false Must be set to true if using HyHeader

Example

<hy-main maxWidth="800px" :resizeTo="90">
    <hy-flex-container>
        <input />
        <button>Hello</button>
        <hy-checkbox />
    </hy-flex-container>
</hy-main>

HyNavigationContainer

HyperUI comes with a basic navigation system consisting of a sidebar and a tabbar UI component. This container can house both of them and automatically switch between them depending on screen size. It also helps aligning the main content next to the sidebar.

Targeting class

hy-navigation-container

Slot

This component has three slots, which is why we need to use named slots.

  1. First, the tabbar for mobile phones and other rather small screens.
    The name of the slot is tabbar.

  2. Second, the sidebar for desktop devices that can fit a sidebar next to the main content.
    The name of the slot is sidebar.

  3. Third, the main content.
    Here, one may place its <router-view>.
    The name of the slot is content.

As these are named slots, they don't have to be in this order. Just make shure you don't forget one of them.

Options

Name Type Default Required Extra info
switchToMobileAt Number 850 - In CSS px. If the screen is smaller than this number, then this component will hide the sidebar and show the tabbar.
maxWidth String "1400px" - Similar to the maxWidth option on the HyMain component. This does apply to the container holding the sidebar and the content, not just the content. It's recommended to wrap your <router-view> in a HyMain component.

Example

<hy-navigation-container>    
    <template #sidebar>
        <hy-navigation-sidebar>
            <!-- Of course, one can put in this slot whatever they want: -->
            <h3>Hello World</h3>

            <!-- It's recommended to use the pre-styled navigation buttons for presenting the different routing destinations -->
            <button @click="$router.push('/home')" class="hy-navigation-option" :class="{ selected: $route.name == 'Home' }">
                <i class="icon-home"></i> <!-- Icon (currently only icon-fonts like fontawesome are officially supported) -->
                <span>Home</span> <!-- Label -->
            </button>

            <button @click="$router.push('/settings')" class="hy-navigation-option" :class="{ selected: $route.name == 'Settings' }">
                <i class="icon-settings"></i>
                <span>Settings</span>
            </button>
        </hy-navigation-sidebar>
    </template>
                
    <template #tabbar>
        <hy-navigation-tabbar>
            <!-- These pre-styled navigation buttons are also in the tabbar available, but they change their style to better fit in the tabbar -->
            <button @click="$router.push('/home')" class="hy-navigation-option" :class="{ selected: $route.name == 'Home' }">
                <i class="icon-home"></i>
                <span>Home</span>
            </button>

            <button @click="$router.push('/settings')" class="hy-navigation-option" :class="{ selected: $route.name == 'Settings' }">
                <i class="icon-settings"></i>
                <span>Settings</span>
            </button>
        </hy-navigation-tabbar>
    </template>

    <template #content>
        <hy-main maxWidth="800px">
            <!-- This example uses Vue Router, but essentially you can put anything in here -->
            <router-view></router-view>
        </hy-main>
    </template>
</hy-navigation-container>

The <hy-navigation-sidebar> and <hy-navigation-tabbar> components are explained below.

HyNavigationSidebar

As part of the navigation system HyperUI offers, there is a Sidebar UI component. It should be placed within a HyNavigationContainer.

Targeting class

hy-navigation-sidebar

Slot

Place any content (e.g. a logo, company name and the available pages) that should be displayed within the sidebar here.

Within this slot, one may use the "hy-navigation-option" class on a <button> element to create a specially designed button that may represent a page that the user can visit. Apply the "selected" class to it and it will be highlighted. Within, you can place a label next to an icon.

The following example will use vue router to create a navigation option, that represents the 'home' page of your app:

<button @click="$router.push('/home')" class="hy-navigation-option" :class="{ selected: $route.name == 'Home' }">
    <!-- Icon (currently only icon-fonts like fontawesome are officially supported) -->
    <i class="icon-home"></i>

    <!-- Label -->
    <span>Home</span>
</button>

Note that this syntax is the same within a <hy-navigation-tabbar> component.

Enable scrolling in sidebar

Scrolling must be enabled if there is too much content within the sidebar and the content does overflow if a screen is too small. Be aware that this is only one possible solution and there might be better looking, but more complicated ways to enable scrolling.

.hy-navigation-sidebar :deep(#visual) {
    overflow-y: scroll;
}

Options

Name Type Default Required Extra info
width String "300px" -
height String "100vh" -
inset String "15px" - Inset to the parent container.

Typically, one does not need to change these properties.

Example

For example look at the HyNavigationContainer's example section

HyNavigationTabbar

As part of the navigation system HyperUI offers, there is a Tabbar UI component. It should be placed within a HyNavigationContainer.
This component looks similar to the tabbar that iOS apps typically have.

Targeting class

hy-navigation-tabbar

Slot

Place the available navigation options that should be displayed within the tabbar here.

Within this slot, one may use the "hy-navigation-option" class on a <button> element to create a specially designed button that may represent a page that the user can visit. Apply the "selected" class to it and it will be highlighted. Within, you can place a label below an icon.

The following example will use vue router to create a navigation option, that represents the 'home' page of your app:

<button @click="$router.push('/home')" class="hy-navigation-option" :class="{ selected: $route.name == 'Home' }">
    <!-- Icon (currently only icon-fonts like fontawesome are officially supported) -->
    <i class="icon-home"></i>

    <!-- Label -->
    <span>Home</span>
</button>

Note that this syntax is the same within a <hy-navigation-sidebar> component.

Options

None.

Example

For example look at the HyNavigationContainer's example section

HyModal

A modal element. Adapts to mobile and desktop devices. Respects the bottom safe-area.

Targeting class

hy-modal

v-model

Syncs the current visibility state with your parent vue instance. View the Info about v-model section for more details. If modelValue is set to true, the modal will show. So you can open the modal programmatically while letting the user close the modal with the build in close button.

Slot

Pass the elements you want to appear within the modal in the slot. Inside, you can directly interact with your Vue instance as it would be normal template code.

Options

Name  Type Default  Extra info
modelValue Boolean - Required. Two-way binding about whether the modal is open or not
zIndex Number 200 Z-Index of modal element
background String null Background (-color) of modal. Defaults to white (or black)
hideScrollbars Boolean true
doBSL Boolean true Whether body scrolling should be disabled or not. If doBSL = true, then the user will only be able to scroll within the modal, not the entire body.
disableDismiss Boolean false If set to true, the user cannot dismiss the modal. This option hides the close button and disabling the 'click-outside-way' of closing the modal.
disableSwipeToClose Boolean false If set to true, swipe to close on touch devices will be disabled and the close button will be shown on every device.
forceFullHeightOnMobile Boolean false Forces full height if the modal is displayed on mobile devices. If false, the modal will only be as high as necessary

IMPORTANT

The modal component uses teleports to get the modal out of the regular component tree, as it would otherwise cause problems with position: fixed.

BUT, in order for this to work, one must specify a target element, preferably outside of the vue instance (for example in index.html). This element should be a div with an #hy-modals-container id. Do not style this element with css! You only need one element for all your modals in your Vue project!
See below for an example.

Example

In your vue template:

<hy-modal v-model="modal.isOpen">
    <h1>My test modal</h1>
    <p>{{ myText }}</p>
    
    <hy-button v-on:click="modal.isOpen = false">
        Close modal
    </hy-button>
</hy-modal>

In index.html:

(...)

<body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>

    <div id="hy-modals-container"></div>
</body>

(...)

HyPopover

A popover container. Floats above the main content and stays attached to the target element with the help of Popper. Will disappear if the user clicks outside of it.
If you set hover to true, then you can use this component as a tooltip.

Attention

Popovers may require a lot of computing resources. We recommend not using too many of them, certainly not in dynamic scenarios (e.g. using v-for). For such applications, please use HyPopoverFree.

Targeting class

hy-popover

v-model

Syncs the current open state with your parent vue instance. View the Info about v-model section for more details. If modelValue is set to true, the popover will show. So you can open the popover programmatically while giving the user the option to close the popover by clicking outside of it. Even if you use the popover as a tooltip that simply shows when the user hovers over an element, you still need to use v-model!

Slot

This component has two slots, which is why we need to use named slots.

  1. First, the target element This can be any element, such as a <p> tag or a HyButton component.
    The name of the slot is element

  2. Second, the popover content popover This is what will appear inside the popover.
    The name of the slot is popover

So, within the components slot, you should pass two <template #nameOfSlot> tags. See the example below for more detail.

Options

Name  Type Default  Extra info
modelValue Boolean Required. Controls whether the popover is shown or not
type String match Color type of popover. Either match or contrast (= dark bg-color if lightmode is active)
zIndex Number 10 Z-Index of popover element
hover Boolean false If true, the popover will show if the user hovers over the target element
hoverDelay Number 700 In MS. Delay to wait before popover will show (only for hover). Aborts if user stops hovering over target element
hideOnClickOutside Boolean true If the user clicks outside, the popover will hide
minWidth String 0 Desired css min-width value, e.g. "400px"
maxWidth String unset Desired css max-width value, e.g. "600px"
maxHeight String unset Desired css max-height value, e.g. "100px"
placement String bottom See Popper options
offsetY Number 15 Y-Offset of popover
offsetX Number 0 X-Offset of popover

Example

<hy-popover v-model="popover.isOpen" minWidth="400px">
    <template #element>
        <hy-button v-on:click="popover.isOpen = !popover.isOpen">Toggle popover</hy-button>
    </template>

    <template #popover>
        <h4>Hello World</h4>
        <hy-input v-model="testInput"/>
    </template>
</hy-popover>

HyPopoverFree

A popover container. Floats above the main content and stays attached to the target element with the help of Popper. Will disappear if the user clicks outside of it.
Does NOT support hover.

Difference to HyPopover

HyPopover was designed to be used "inline" with one element.
If you want to have one popover component and be able to attach it to different elements, then please use this component.
A popover may require a lot of computing resources. Use HyPopoverFree in dynamic situations (e.g. when using v-for): one HyPopoverFree that may attach to different elements depending on the situation.

Targeting class

hy-popover-free

v-model

Syncs the current open state with your parent vue instance. View the Info about v-model section for more details. If modelValue is set to true, the popover will show. So you can open the popover programmatically while giving the user the option to close the popover by clicking outside of it.

Slot

Popover content. This is what will appear inside the popover.
Unlike HyPopover, here you do not pass the target element via a slot. Instead, the target element is passed to the component via props.

Options

Name  Type Default  Extra info
modelValue Boolean Required. Controls whether the popover is shown or not
element HTMLElement null Required. Target element to which the popover should attach to. If changed, the popover will attach to the new element
type String "match" Color type of popover. Either match or contrast (= dark bg-color if lightmode is active)
zIndex Number 10 Z-Index of popover element
hideOnClickOutside Boolean true If the user clicks outside, the popover will hide
minWidth String 0 Desired css min-width value, e.g. "400px"
maxWidth String unset Desired css max-width value, e.g. "600px"
maxHeight String unset Desired css max-height value, e.g. "100px"
placement String "bottom" See Popper options
offsetY Number 15 Y-Offset of popover
offsetX Number 0 X-Offset of popover

IMPORTANT

The popover-free component uses teleports to get the popover out of the regular component tree.

BUT, in order for this to work, one must specify a target element, preferably outside of the vue instance (for example in index.html). This element should be a div with an #hy-popovers-container id. Do not style this element with css! You only need one element for all your free-floating popovers in your Vue project!
See below for an example.

Example

Vue template:

<hy-popover-free v-model="myPopover.isOpen" :element="myPopover.targetElement">
    <p>Popover</p>
</hy-popover-free>

<!-- Just some example elements the popover can attach to -->
<!-- We use pointer-events: none on the icons to prevent the popover from attaching to the icon instead of the button -->
<hy-flex-container>
    <hy-button @click="openPopover($event.target)"> <i class="icon-printer" style="pointer-events: none"></i> </hy-button>
    <hy-button @click="openPopover($event.target)"> <i class="icon-image" style="pointer-events: none"></i> </hy-button>
    <hy-button @click="openPopover($event.target)"> <i class="icon-megaphone" style="pointer-events: none"></i> </hy-button>
    <hy-button @click="openPopover($event.target)"> <i class="icon-calendar" style="pointer-events: none"></i> </hy-button>
    <hy-button @click="openPopover($event.target)"> <i class="icon-home" style="pointer-events: none"></i> </hy-button>
    <hy-button @click="openPopover($event.target)"> <i class="icon-lock-open" style="pointer-events: none"></i> </hy-button>
</hy-flex-container>

Within your Vue instance:

data() {
    return {
        myPopover: {
            targetElement: null,
            isOpen: false,
        }
    }
},
methods: {
    openPopover(targetElement) {
        this.myPopover.targetElement = targetElement;

        // Sometimes, using vue's $nextTick is required. See Known Issues for more detail.
        this.$nextTick(() => {
            this.myPopover.isOpen = true;
        }
    },
},

In index.html:

(...)

<body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>

    <div id="hy-modals-container"></div>
</body>

(...)

Known issues

If you receive this error:
HyperUI Error: Target element found but not yet rendered. Please try wrapping code updating the modelValue in this.$nextTick()
Then wrapping the code responsible for updating the modelValue in this.$nextTick() might help:

function openMyPopover(el) {
    // Setting the target element
    this.myPopoverFree.element = el;

    // Open popover
    this.$nextTick(() => {
        this.myPopoverFree.open = true;
    });
}

HySmartMenu

Sometimes a modal is just right for mobile devices but too big on desktops. A smart menu is a modal on mobile that turns into a compact popover on desktop. This components uses HyModal and HyPopover under the hood.

Attention

As smart menus use popovers, they may require a lot of computing resources. We recommend not using too many of them, certainly not in dynamic scenarios (e.g. using v-for).
In dynamic scenarios, HySmartMenuFree might work better.

Targeting class

hy-smart-menu

v-model

Syncs the current open state with your parent vue instance. View the Info about v-model section for more details. If modelValue is set to true, the menu will show.

Slot

This component has two slots, which is why we need to use named slots.

  1. First, the target element element
    This can be any element, such as a <p> tag or a HyButton component.
    The name of the slot is element

  2. Second, the menu content menu
    This is what will appear inside the menu (on desktop and mobile).
    The name of the slot is menu
    A menuType variable is exposed to this slot. Read more about so called Scoped Slots

So, within the components slot, you should pass two <template #nameOfSlot> tags. See the example below for more detail.

Options

Name  Type Default  Extra info
modelValue Boolean Required. Controls whether the menu is shown or not

Additionally, this menu supports these properties from HyModal (if mobile device):

background, hideScrollbars, doBSL, disableSwipeToClose, disableDismiss, forceFullHeightOnMobile

Additionally, this menu supports these properties from HyPopover (if desktop device):

hideOnClickOutside, minWidth, maxWidth, maxHeight, type, placement, offsetY, offsetX

Example

<!-- Use properties from both HyPopover and HyModal -->
<hy-smart-menu v-model="mySmartMenu.isOpen" maxWidth="400px" background="#000">
    <template #element>
        <hy-button @click="mySmartMenu.isOpen = !mySmartMenu.isOpen">Toggle smart menu</hy-button>
    </template>

    <template #menu>
        <h2>Smart Menu</h2>
        <p>A smart menu is a modal on mobile that turns into a compact popover on desktop.</p>

        <hy-button @click="mySmartMenu.isOpen = false" type="primary">Close this smart menu</hy-button>
    </template>
</hy-smart-menu>

Access the menuType variable exposed to the slot:

<!-- Notice the syntax for a named scoped slot. Refer to the vue docs for more info. -->
<template #menu="{ menuType }">
    <p>{{ menuType }}</p>
</template>

HySmartMenuFree

A smart menu using HyPopoverFree, which may be better suited in dynamic situations.
This components uses HyModal and HyPopoverFree under the hood.

For docs, please refer to HySmartMenu and look into HyPopoverFree for troubleshooting.

Attention

As smart menus use popovers, they may require a lot of computing resources. We recommend not using too many of them.
In dynamic situations (e.g. when using v-for) use one HySmartMenuFree that may attach to different elements depending on the situation.

Targeting class

hy-smart-menu-free

Slot

Unlike HySmartMenuFree, here you do not pass the target element via a slot. Instead, the target element is passed to the component via props. Therefore, only the default slot exists.

Options

Additional to the options posted in HySmartMenu, this component inherits the element option from HyPopoverFree.

Example

<hy-smart-menu-free v-model="mySmartMenu.isOpen" :element="mySmartMenu.targetElement">
    <p>Hello World</p>
</hy-smart-menu-free>

Attention: Accessing menuType is different on this component:

<!-- Notice the syntax for this scoped slot as well as the position compared to a regular HySmartMenu. Refer to the vue docs for more info -->
<hy-smart-menu-free v-slot="{ menuType }">
    <p>{{ menuType }}</p>
</hy-smart-menu-free>

HyListIcon

An iOS style list icon. Best used within sections with automatic dividers turned on to create an elegant e.g. settings page.

Targeting class

hy-list-icon

Slot

Pass your icon in there. Build for icon-fonts.

Options

Name  Type Default  Extra info
color String "transparent" Background color. Use blue, pink, orange, green, red, light-blue or purple. The font/icon color will be adjusted automatically to fit the background.

Example

<hy-list-icon color="light-blue">
    <i class="icon-printer"></i> <!-- Your icon -->
</hy-list-icon>

Best used in sections:

<hy-section :dividers="true">

    <hy-flex-container :allowBreak="false">
        <hy-list-icon color="pink"> <i class="icon-printer"></i> </hy-list-icon>

        <hy-toggle type="right"> Toggle this </hy-toggle>
    </hy-flex-container>

    <hy-flex-container :allowBreak="false">
        <hy-list-icon color="orange"> <i class="icon-plus-circle"></i> </hy-list-icon>
    
        <p>Look at this</p>
    </hy-flex-container>

</hy-section>

HyHeader

A header component. Sticks to the top of the screen on mobile and floats on desktop devices.

Attention

The following steps must be taken if using this component

  • On HyMain, the property usingHyHeader MUST be set to true

  • Use the same values for the properties maxHeight and resizeTo as on HyMain

  • Use the same value for the property inset as on HyNavigationSidebar

  • Use the same value for the property switchToMobileAt as on HyNavigationContainer

  • Always place the header inside the HyMain component

  • Put this in your HTML head:

    <meta name="theme-color" content="#fff" media="(prefers-color-scheme: light)" />
    
    <meta name="theme-color" content="hsl(220, 5%, 13%)" media="(prefers-color-scheme: dark)" />

Targeting class

hy-header

Slot

Pass any necessary elements in here. As the header is a hy-flex-container, these will be arranged next to the headline.

Options

Name  Type Default  Extra info
headline String null
icon String null Name of an icon to display left of headline. Uses an <i class="..." />
doCoverShadow Boolean true Adds a shadow underneath. Lets elements scrolling underneath fade into the void
floating Boolean true Do floating look on desktop devices
extendHeadline Boolean true Controls .hy-extend-full class on headline element
maxWidth String 1400px Must be same value as corresponding property on HyMain
resizeTo Number 95 Must be same value as corresponding property on HyMain
inset String 15px Must be same value as corresponding property on HyNavigationSidebar
switchToMobileAt Number 850 Must be same value as corresponding property on HyNavigationContainer

Example

<hy-header maxWidth="800px" :resizeTo="90" headline="HyperUI" icon="icon-home">
    <!-- Any additional elements go here -->
</hy-header>

Floating Badge

This is not a component but rather a utility class.

To activate, apply to any element the class hy-floating-badge.
Now you may specify the text to display via an data-badge-text attribute. You may use v-bind:data-badge-text to bind the attribute to a reactive vue variable (see example 2). This attribute can be ommited (or fed an empty string) to just show a small dot above the target element (see example 3).

Examples

Example 1:

<hy-button class="hy-floating-badge" data-badge-text="10k">Show the News</hy-button>

Example 2:

<hy-button class="hy-floating-badge" v-bind:data-badge-text="myBadgeText">Show the News</hy-button>

<hy-input v-model="myBadgeText" placeholder="Badge text"></hy-input>

Example 3:

<hy-button class="hy-floating-badge">Show the News</hy-button>

CSS Documentation

Every component has a class for easy css targeting. These classes are specified in the Component Documentation under Targeting class.

Utility Classes

hy-reset

The library puts certain styles on text elements like p or h1 tags. You can disable this by adding class="hy-reset" to that specific element.

hy-extend-full

Applies flex: 100 !important to an element. Useful in a <hy-flex-container> if all other elements should shrink to their minimal size.

See this example:

<hy-flex-container>
    <h3 class="hy-extend-full">My element</h3>

    <hy-button>Do action</hy-button>
</hy-flex-container>

On desktop, the button will shrink automatically to it's minimal size to give the h3 room.
On mobile, these elements will be arranged beneath each other automatically, both having the same size and without one element being weirdly shaped or having the wrong width.

hy-remove-leading-trailing-margins

Removes the top-margin from the first child and the bottom-margin from the last child.
Ever noticed the Section or Popover components doing exactly this?

hy-remove-leading-margins

Removes the top-margin from the first child.

hy-remove-trailing-margins

Removes the bottom-margin from the last child.

hy-no-margin

This removes margins (and paddings).

hy-label

Removes the distance between itself and the element beneath it. Also makes the space between itself and the previous element bigger. Can only be used on p-Tags!

hy-element-shadow

Just adds a shadow, like a button has.

hy-section-shadow

Build for increasing contrast if working with sections. (But it works on any component). If you want this to be default for every section, then add these lines of code to your css:

.hy-section {
    box-shadow: var(--section-shadow);
}

hy-text-[COLOR]

Changes font color of the element and all its childs. Available classes are:

  • hy-text-accent
  • hy-text-blue
  • hy-text-pink
  • hy-text-yellow
  • hy-text-green
  • hy-text-red
  • hy-text-light-blue
  • hy-text-purple
  • hy-text-accent
  • hy-text-gray-1
  • hy-text-gray-2
  • hy-text-gray-3

hy-border-accent

Applies a border color of the accent color (border-color: var(--accent-color)) to the element and all its top level childs.

hy-font-weight-bold

Applies a font weight of bold to the element and all its level childs.

hy-font-weight-normal

Applies a font weight of normal to the element and all its level childs.

hy-hide-scrollbars

Tries to hide scrollbars of that element.

hy-bg-[COLOR]

Instantly apply a background-color for an element from your html. Available classes are:

  • hy-bg-blue
  • hy-bg-pink
  • hy-bg-yellow
  • hy-bg-green
  • hy-bg-red
  • hy-bg-light-blue
  • hy-bg-purple
  • hy-bg-accent
  • hy-bg-gray-1
  • hy-bg-gray-2
  • hy-bg-gray-3

hy-floating-badge

View documentation here.

CSS Variables

General Variables

--font-size: 20px;
--font-family: Arial, Helvetica, sans-serif;

--flex-gap: 10px;
--section-padding: 20px;
--section-border-radius: calc(2 * var(--element-border-radius));
--section-shadow: 0 0 32px 5px var(--section-shadow-color);
--section-divider: 2px solid var(--section-divider-color);

--element-border-secondary: 2px solid var(--element-border-secondary-color);
--element-border-accent: 2px solid var(--accent-color);

--element-margin: 18px 0;
--element-padding: 15px;
--element-padding-light: 10px;
--element-padding-thin: 5px;

--element-transition: none 0.2s ease-in-out;
--element-shadow: 0px 4px 8px -2px var(--element-shadow-color);
--element-border-radius: 10px;

--popover-shadow: 0 0 32px 15px var(--popover-shadow-color);

--tabbar-shadow: 0 0 25px 5px var(--tabbar-shadow-color);
--sidebar-shadow: 0px 0px 25px 5px var(--sidebar-shadow-color);
--header-shadow-cover: 0px 0px 30px 20px var(--body-bg-color);

General Variables adjusted on mobile

(if device width is smaller than 600px)

--font-size: 18px;
--element-padding: 13px;
--section-padding: 18px;

Lightmode colors

--font-color-white: white;
--font-color-black: hsl(210, 29%, 24%);

--font-color-contrast: var(--font-color-black); // Default in light theme => "Contrast" to the background color
--font-color-match: var(--font-color-white);

// DEPRECATED => Use "contrast" / "match" colors instead
--font-color-dark: var(--font-color-contrast);
--font-color-bright: var(--font-color-match);

// General
--body-bg-color: hsl(240, 13%, 94%);
--accent-color: var(--color-blue);
--loader-ring-bg-color: hsl(0, 0%, 87%);

// Theme Colors
--color-blue: hsl(222, 100%, 61%);
--color-pink: hsl(340, 82%, 49%);
--color-yellow: hsl(44, 97%, 50%);
--color-green: hsl(116, 45%, 54%);
--color-red: hsl(0, 76%, 58%);
--color-light-blue: hsl(205, 100%, 62%);
--color-purple: hsl(321, 62%, 46%);
--color-gray-1: hsl(231, 8%, 83%);
--color-gray-2: hsl(240, 8%, 88%);
--color-gray-3: hsl(240, 8%, 97%);

// Sections: Colors
--section-shadow-color: hsla(0, 0%, 41%, 0.1);
--section-bg-color: white;

// Element: Primary Colors
--element-primary-bg-color: var(--accent-color);
--element-primary-hover-bg-color: hsl(222, 100%, 53%);

// Element: Secondary Colors
--element-secondary-bg-color: var(--section-bg-color);
--element-secondary-hover-bg-color: hsl(0, 0%, 96%);
--element-border-secondary-color: hsl(0, 0%, 76%);

// Element: Others
--element-shadow-color: hsla(0, 0%, 72%, 0.33);
--section-divider-color: hsl(0, 0%, 88%);

// Button light colors
--button-transparent-bg: hsla(230, 11%, 85%, 0.145);
--button-transparent-hover: hsla(230, 11%, 72%, 0.145);

--button-light-blue-bg: hsla(214, 100%, 85%, 0.27);
--button-light-blue-hover: hsla(214, 100%, 70%, 0.27);
--button-light-blue-font: hsl(214, 85%, 50%);

--button-light-red-bg: hsla(0, 100%, 88%, 0.29);
--button-light-red-hover: hsla(0, 100%, 73%, 0.29);
--button-light-red-font: var(--color-pink);

--button-light-orange-bg: hsla(44, 100%, 87%, 0.53);
--button-light-orange-hover: hsla(44, 100%, 75%, 0.53);
--button-light-orange-font: hsl(44, 100%, 50%);

--button-light-green-bg: hsla(114, 100%, 82%, 0.22);
--button-light-green-hover: hsla(114, 100%, 52%, 0.22);
--button-light-green-font: hsl(115, 88%, 51%);

// Modal
--modal-bg-color: var(--section-bg-color);
--modal-cover-color-mobile: hsla(0, 0%, 26%, 0.6);
--modal-cover-color-desktop: hsla(0, 0%, 100%, 0.5);
--modal-shadow-color: hsla(0, 0%, 60%, 0.4);

// Popover
--popover-shadow-color: hsla(0, 0%, 41%, 0.17);
--popover-bg-color-match: var(--section-bg-color);
--popover-bg-color-contrast: hsl(220, 5%, 13%); // Darkmode section-bg-color

// Navigation
--tabbar-shadow-color: hsla(0, 0%, 81%, 0.56);
--sidebar-shadow-color: var(--tabbar-shadow-color);

Darkmode colors

--font-color-white: hsl(0, 0%, 80%);
--font-color-black: hsl(0, 0%, 20%);

--font-color-contrast: var(--font-color-white); // Default in dark theme => "Contrast" to the background color
--font-color-match: var(--font-color-black);

// DEPRECATED => Use "contrast" / "match" colors instead
--font-color-dark: var(--font-color-contrast);
--font-color-bright: var(--font-color-match);

// General
--body-bg-color: black;
--accent-color: var(--color-blue);
--loader-ring-bg-color: hsl(0, 0%, 35%);

// Theme Colors
--color-blue: hsl(222, 100%, 68%);
--color-pink: hsl(340, 82%, 49%);
--color-yellow: hsl(44, 97%, 50%);
--color-green: hsl(116, 45%, 54%);
--color-red: hsl(0, 76%, 58%);
--color-light-blue: hsl(205, 100%, 62%);
--color-purple: hsl(321, 62%, 46%);
--color-gray-1: hsl(228, 12%, 8%);
--color-gray-2: hsl(231, 11%, 12%);
--color-gray-3: hsl(227, 5%, 18%);

// Sections: Colors
--section-shadow-color: hsla(0, 0%, 3%, 0.5);
--section-bg-color: hsl(220, 5%, 13%);

// Element: Primary Colors
--element-primary-bg-color: hsl(0, 0%, 90%);
--element-primary-hover-bg-color: hsl(0, 0%, 75%);

// Element: Secondary Colors
--element-secondary-bg-color: var(--section-bg-color);
--element-secondary-hover-bg-color: hsl(231, 8%, 17%);
--element-border-secondary-color: hsl(0, 0%, 40%);

// Element: Others
--element-shadow-color: hsla(0, 0%, 0%, 0.4);
--section-divider-color: hsl(0, 0%, 27%);

// Button light colors
--button-transparent-bg: hsla(224, 9%, 30%, 0.15);
--button-transparent-hover: hsla(224, 9%, 30%, 0.25);

--button-light-blue-bg: hsla(214, 63%, 33%, 0.1);
--button-light-blue-hover: hsla(214, 63%, 53%, 0.15);
--button-light-blue-font: hsl(214, 65%, 61%);

--button-light-red-bg: hsla(0, 65%, 38%, 0.1);
--button-light-red-hover: hsla(0, 65%, 48%, 0.15);
--button-light-red-font: var(--color-pink);

--button-light-orange-bg: hsla(44, 78%, 16%, 0.3);
--button-light-orange-hover: hsla(44, 78%, 26%, 0.35);
--button-light-orange-font: hsl(44, 100%, 50%);

--button-light-green-bg: hsla(114, 51%, 49%, 0.1);
--button-light-green-hover: hsla(114, 100%, 50%, 0.15);
--button-light-green-font: hsl(115, 73%, 47%);

// Modal
--modal-bg-color: var(--section-bg-color);
--modal-cover-color-mobile: hsla(0, 0%, 0%, 0.85);
--modal-cover-color-desktop: hsla(0, 0%, 0%, 0.85);
--modal-shadow-color: hsl(0, 0%, 0%);

// Popover
--popover-shadow-color: hsla(0, 0%, 3%, 0.5);
--popover-bg-color-match: var(--section-bg-color);
--popover-bg-color-contrast: white; // Lightmode section-bg-color

// Navigation
--tabbar-shadow-color: hsla(0, 0%, 0%, 0.6);
--sidebar-shadow-color: var(--tabbar-shadow-color);

Tips & Tricks

Re-Style Components

Sometimes it may be necessary to update the styles of a component. If you just want to re-style a section, that's easy. But it becomes more difficult if you are working with scoped css and want to update a child node of a component, e.g. the visual of a button.

First, we need to understand how some components are build. Many of them are nested inside a container which is responsible for tasks such as positioning elements or itself in a parent.

A child of this container would be the actual <button> element (for example), which has default css properties like a background-color or a border-radius. If you want to change these, but still continue working within scoped css, you will quickly realize that you are able to style the container (by selecting it with the correct class; see component docs), but not so easy the actual button.

To work around these issues, Vue proposes to using the :deep() pseudo-class, or you can style the elements from a non-scoped css block.

With :deep()

<style scoped>
    .hy-button :deep(button) {
        background-color: yellow;
    }
</style>

Styling outside of a scoped environment

<style scoped>
    /* Other styles */
</style>

<style>
    .hy-button button {
        background-color: yellow;
    }
</style>

You may also need to make these rules !important, depending on your selector specificity.

How v-model works

Often, components use v-model. This directive allows these components to sync a state variable between the component and the parent Vue instance. You may want to read this introduction from the official Vue docs.
Essentially, v-model="someVariable" is a shorthand for :modelValue="someVariable" @update:modelValue="newValue => someVariable = newValue".

So these two pieces of code do the same thing:

<hy-input v-model="someVariable" />

<hy-input :modelValue="someVariable" @update:modelValue="newValue => someVariable = newValue" />

This extended syntax allows for more customization, so you could, for example, call a method if the modelValue changes.

If you see a modelValue attribute that is required in the docs for a HyperUI component, than this is just a fancy way of saying that this components needs a v-model binding to do its job. Often we use v-model to sync an important state of an component, like whether the modal is open or not.

The size option

Currently, the size option supports normal, light and thin. This option can be set individually for each element or via HyperUI config globally.

Changelogs

Version 3.1.0

  • HyperUI now automatically adds the hy-modals-container and hy-popovers-container to the DOM. You may now remove them from your codebase.

Version 3.0.0

  • Added hy-smart-menu and hy-smart-menu-free as a compromise between a modal and a popover
  • Added hy-header component
  • Added hy-progress-bar component
  • Added size option to Button, Input and Select components
  • Added new light-bg type options for Button component
  • Section now also supports title, pre and post
  • Section and Sub-Sections can now be collapsed
  • Redesigned hy-table
  • Added option to show a progress bar instead of a loading spinner on supported components

Attention: we changed the target classes of elements to reflect new naming scheme
-> See Breaking Changes for additional updates

Version 2.6.0

  • Added Free-Floating hy-popover-free as an alternative to the fixed hy-popover. This component can be attached to multiple target elements
  • Ff a device supports touch events, modals can now be closed by swiping
  • Darkmode: Primaries now use the blue accent color
  • Added maxWidth and maxHeight property to popovers
  • Added .hy-remove-leading-margins utility class
  • Added .hy-remove-trailing-margins utility class

Version 2.5.0

  • Redesign modal for desktop devices

Version 2.4.0

  • Added navigation related components:
    • Added NavigationContainer component, that switches between a tabbar and a sidebar
    • Added NavigationSidebar component
    • Added NavigationTabbar component
  • Added a toggle "checkbox" component
  • Added an iOS inspired ListIcon component
  • Tweaked background-color of transparent buttons
  • Tweaked darkmode colors
  • Added hy-extend-full utility class
  • Added hy-text-[COLOR] utility classes
  • Added icons for Input fields and Selects
  • --font-color-dark & --font-color-bright are DEPRECATED, use --font-color-contrast and font-color-similar instead
  • Added .hy-remove-leading-trailing-margins utility class

Version 2.3.0

  • Added dropzones for easier file reading and uploading

Version 2.2.0

  • Added radio buttons

Version 2.1.0

  • Added floating badges
  • Renamed utility classes to include the hy- prefix. Old utility class names are DEPRECATED

Version 2.0.0

  • Renamed components to include the prefix "Hy"
  • Attention: CSS variable names have changed
  • Switched to a new bundler => You're required to import the styles for yourself
  • New light and transparent colored button style
  • Modals
  • Popovers & Tooltips
  • New sub-section component
  • Inputs now support non-string values. But, it may still return a string if the user changes the value
  • Checkboxes now have a right aligned mode
  • Select between "light" and "dark" theme, or just use both of them automatically with config value "system"
  • Docs for CSS variables
  • Adjusted theme colors
  • Section Border Radius CSS variable
  • .section-shadow utility class
  • Docs for :deep() pseudo-class in re-style components
  • Bugfixes

Version 1.4.0

  • Color theme updates:
    • New Dark Blue instead of Black
    • New Accent Color is based on a red color (Light- & Darkmode)
  • Buttons will have a default font-weight of bold
  • New .fontWeightNormal utility class. Reverts the previously noticed changes to a font-weight of normal.
  • New .fontWeightBold utility class.
  • New .borderAccent utility class. Turns the border color of a button (or a similar element) into the accent color.

Version 1.3.0

  • Added TextAreas
  • Buttons got a new, transparent Style
  • New .textAccent utility class for easily changing the text color to the accent color. Developed for being used with the new Button Style
  • Use Vue $attrs for Inputs & Texareas (more info in the component docs)

Version 1.2.0

  • Flex: Use gap property withing flex-containers
  • Flex: Removed the generic 5px margin
  • Attention: Safari has been supporting the gap property since May 2021 which means not a lot of people have received the update yet. Consider waiting to update this library!
  • Added a tabbar
  • Elements get smaller on mobile screens

Version 1.1.0

  • Button: New accent-color style
  • Updated accent colors to orange colors
  • Switched colors for section and body background in darkmode

Readme

Keywords

none

Package Sidebar

Install

npm i @jaaahn/hyper-ui

Weekly Downloads

117

Version

3.1.1

License

MIT

Unpacked Size

572 kB

Total Files

42

Last publish

Collaborators

  • jaaahn