-
Notifications
You must be signed in to change notification settings - Fork 0
Expandable
Mahdi-Movahedian-Atar edited this page Aug 16, 2024
·
1 revision
export const App = component$(() => {
return (
<Button>
<Expandable
visible={true}
color="success"
variant="solid"
direction="down"
maxHeight={150}
>
<div>This content expands.</div>
</Expandable>
</Button>
)
});
Property | Type | Description |
---|---|---|
class |
string |
Custom CSS class for the component. (default: undefined ) |
visible |
boolean |
Determines if the expandable content is visible. (default: false ) |
style |
CSSProperties |
Inline styles for the expandable container. (default: { height: 'fit-content', width: 'fit-content' } ) |
color |
'success' | 'error' | 'warning' | 'accent' | 'primary' |
Color variant for the expandable component. (default: 'primary' ) |
variant |
'solid' | 'outlined' | 'text' |
Visual style of the expandable component. (default: 'outlined' ) |
maxHeight |
number |
Maximum height of the expandable content in pixels. (default: 100 ) |
direction |
'down' | 'up' | 'left' | 'right' |
Direction in which the content expands. (default: 'down' ) |
export interface ExpandableProps {
class?: string
visible?: boolean
style?: CSSProperties
color?: 'success' | 'error' | 'warning' | 'accent' | 'primary'
variant?: 'solid' | 'outlined' | 'text'
maxHeight?: number
direction?: 'down' | 'up' | 'left' | 'right'
}
export const Expandable = component$<ExpandableProps>(
({
visible = false,
class: className,
style = {
height: 'fit-content',
width: 'fit-content',
},
variant = 'outlined',
color = 'primary',
maxHeight = 100,
direction = 'down',
}) => {
const ref = useSignal<Element>()
useVisibleTask$(() => {
const element = ref.value?.getBoundingClientRect()
if (element == undefined) return
const elementPosition = [
element.bottom,
element.top,
element.left,
element.right,
]
if (direction == 'left' || direction == 'right') {
elementPosition[0] += element.height / 2
elementPosition[1] -= element.height / 2
}
if (elementPosition[0] > window.innerHeight) {
// @ts-ignore
ref.value.style.top = 'unset'
// @ts-ignore
ref.value.style.bottom = '0vh'
// @ts-ignore
ref.value.style.transform = 'unset'
}
if (elementPosition[1] < 0) {
// @ts-ignore
ref.value.style.bottom = 'unset'
// @ts-ignore
ref.value.style.top = '0vh'
// @ts-ignore
ref.value.style.transform = 'unset'
}
if (elementPosition[2] < 0) {
// @ts-ignore
ref.value.style.right = 'unset'
// @ts-ignore
ref.value.style.left = '0vh'
}
if (elementPosition[3] > window.innerWidth) {
// @ts-ignore
ref.value.style.left = 'unset'
// @ts-ignore
ref.value.style.right = '0vw'
}
})
return (
<div class={className} style={style}>
{visible && (
<div
class={`cc-expandable cc-expandable-${variant} cc-expandable-${color}`}
style={{
maxHeight,
bottom: direction == 'up' ? '100%' : 'unset',
top:
direction == 'down'
? '100%'
: direction == 'left' || direction == 'right'
? '50%'
: 'unset',
left: direction == 'right' ? '100%' : 'unset',
right: direction == 'left' ? '100%' : 'unset',
transform:
direction == 'left' || direction == 'right'
? 'translateY(-50%)'
: 'unset',
}}
ref={ref}
>
<Slot />
</div>
)}
</div>
)
}
);
.cc-expandable {
border-radius: var(--corner);
overflow: hidden;
overflow-y: auto;
position: absolute;
width: 100%;
z-index: 9999;
border: var(--width) solid;
padding: var(--width);
cursor: pointer;
scrollbar-width: thin;
scrollbar-color: currentColor var(--secondary-0);
scrollbar-arrow-color: currentColor;
scrollbar-gutter: both-edges;
}
.cc-expandable-primary {
background: var(--primary-0);
border-color: var(--primary-0);
color: var(--primary-0);
}
.cc-expandable-success {
background: var(--success-0);
border-color: var(--success-0);
color: var(--success-0);
}
.cc-expandable-error {
background: var(--error-0);
border-color: var(--error-0);
color: var(--error-0);
}
.cc-expandable-warning {
background: var(--warning-0);
border-color: var(--warning-0);
color: var(--warning-0);
}
.cc-expandable-accent {
background: var(--accent-0);
border-color: var(--accent-0);
color: var(--accent-0);
}
.cc-expandable-solid {
color: var(--secondary-0);
}
.cc-expandable-text {
border-color: transparent;
background: transparent;
}
.cc-expandable-outlined {
background: transparent;
}