e-header v1.0
The <e-header> component is a component that can be used for .
Usage
An e-header has attributes that must be provided,
<e-header
:text="'example text'"
/>
Attributes
icon | Type: String | Default:
''
color | Type: String | Default:''
text | Type: String | required
subText | Type: String | Default:''
subTextColor | Type: String | Default:''
type | Type: String | Default:'border'
heading | Type: String | Default:h2
functionList | Type: FunctionModel[] | Default:[]
const testData = {
text: 'example text',
icon: '',
type: 'border',
heading: 'h2'
}
Examples
Below a few interactive examples of e-header can be found.
basic
<e-header
:text="'h2 example'"
/>
<e-header
:text="'h3 example'"
:heading="'h3'"
/>
<e-header
:text="'h4 example'"
:heading="'h4'"
/>
h2 example
h3 example
h4 example
with icon
<e-header
:text="'h2 example'"
:icon="'checked-circle'"
/>
<e-header
:text="'h3 example'"
:icon="'checked-circle'"
:heading="'h3'"
/>
<e-header
:text="'h4 example'"
:icon="'checked-circle'"
:heading="'h4'"
/>
h2 example
h3 example
h4 example
overwrite color
<e-header
:text="'h2 example'"
:icon="'checked-circle'"
:color="'red'"
/>
<e-header
:text="'h3 example'"
:icon="'checked-circle'"
:color="'white'"
:heading="'h3'"
/>
<e-header
:text="'h4 example'"
:icon="'checked-circle'"
:color="'blue'"
:heading="'h4'"
/>
h2 example
h3 example
h4 example
Source Code
e-header.vue
<script setup lang="ts">
import { computed } from 'vue';
import { isEmpty, merge } from 'lodash-es';
import { FunctionModel } from 'types/FunctionModel';
import { HeadingType } from 'types/General';
import { ThemeStyle, type ThemeStyles } from 'types/Themes';
import EIcon from '../e-icon/e-icon.vue';
import EFunctionBar from '../e-function-bar/e-function-bar.vue';
export type Props = {
icon?: string;
color?: string;
text?: string;
subText?: string;
subTextColor?: string;
collapsible?: boolean;
type?: ThemeStyles;
heading?: HeadingType;
functionList?: FunctionModel[];
};
const props = withDefaults(defineProps<Props>(), {
icon: null,
color: '',
text: null,
subText: null,
collapsible: false,
subTextColor: '',
type: ThemeStyle.Border,
heading: HeadingType.H2,
functionList: () => {
return [] as FunctionModel[];
}
});
const emit = defineEmits<{
(e: 'emit:function', func: FunctionModel): void;
(e: 'emit:collapse'): void;
}>();
const classes = computed(() => {
const result = [];
if (props.type) result.push(props.type);
if (props.collapsible) result.push('collapsible');
return result;
});
const iconColor = computed(() => {
if (!isEmpty(props.color)) return props.color;
switch (props.heading) {
case HeadingType.H2:
case HeadingType.H3:
case HeadingType.H4:
return `var(--e-${props.heading}-color)`;
default:
return 'var(--e-foreground)';
}
});
const headerText = computed(() => {
return props.text;
});
const headerSubText = computed(() => {
return props.subText;
});
const hasSubText = computed(() => !isEmpty(headerSubText.value));
const headerPrimaryStyle = computed(() => {
// only overwrite, if a color is provided
return {
color: isEmpty(props.color) ? '' : props.color
};
});
const headerSubStyle = computed(() => {
return {
color: isEmpty(props.subTextColor) ? iconColor.value : props.subTextColor
};
});
const headerFunctions = computed(() => {
const result: FunctionModel[] = [];
if (!isEmpty(props.functionList)) {
merge(result, props.functionList);
}
return result;
});
const hasFunctions = computed(() => {
return !isEmpty(headerFunctions.value);
});
function handleEmit(func: FunctionModel) {
emit('emit:function', func);
}
</script>
<template>
<div
class="e-header"
:class="classes"
@click="props.collapsible && emit('emit:collapse')"
>
<div
v-if="icon"
class="header-icon"
>
<e-icon
:icon="[icon]"
:color="iconColor"
:focusable="false"
/>
</div>
<div class="header-content">
<div class="primary-header">
<component
:is="heading"
class="header-text"
:style="headerPrimaryStyle"
:title="headerText"
:aria-label="headerText"
>
{{ headerText }}
</component>
<e-function-bar
v-if="hasFunctions"
:function-list="headerFunctions"
@emit:function="handleEmit"
/>
</div>
<div
v-if="hasSubText"
class="sub-header"
>
<p
:style="headerSubStyle"
:aria-label="headerSubText"
:title="headerSubText"
v-text="headerSubText"
/>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
$primary-height: 40px;
.e-header {
width: 100%;
display: flex;
flex-direction: row;
gap: 15px;
overflow: hidden;
&.collapsible {
cursor: pointer;
}
.header-icon {
display: flex;
flex-direction: row;
align-items: center;
height: $primary-height;
.e-icon {
height: 30px;
width: 30px;
pointer-events: none;
}
}
.header-content {
display: flex;
flex-direction: column;
flex: 1 1 auto;
overflow: hidden;
justify-content: space-between;
.primary-header,
.sub-header {
align-items: center;
display: flex;
flex: 1 1 auto;
gap: 15px;
justify-content: space-between;
flex-direction: row;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
.header-text {
display: block;
margin: 0;
padding: 0;
border-bottom: none;
overflow: hidden;
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
}
.e-function-bar {
flex: 0 0 auto;
}
}
.primary-header {
height: $primary-height;
}
.sub-header {
p {
margin: 0;
}
}
}
&.solid,
&.border {
margin: 0;
}
}
</style>