Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Select Component #6

Merged
merged 1 commit into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions app/src/components/ui/select.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import gleam/string
import lustre/attribute.{type Attribute, class}
import lustre/element.{type Element}
import lustre/element/html.{div, label}

pub type Colors {
Neutral
Primary
Secondary
Success
Info
Warning
Danger
}

pub fn select(
attributes: List(Attribute(a)),
children: List(Element(a)),
) -> Element(a) {
label([class("relative")], [
html.select(
[
class(
"appearance-none enabled:cursor-pointer disabled:opacity-50 [&:disabled+div]:opacity-50 disabled:cursor-not-allowed w-full",
),
..attributes
],
children,
),
div(
[
class(
[
"pointer-events-none",
"before:absolute before:size-1 before:right-4 before:pointer-events-none",
"before:border-4 before:border-x-transparent before:border-t-0 before:border-b-current before:top-1/2 before:-translate-y-[133.333333%]",
"after:absolute after:size-1 after:right-4 after:pointer-events-none",
"after:border-4 after:border-x-transparent after:border-b-0 after:border-t-current after:top-1/2 after:translate-y-1/3",
]
|> string.join(" "),
),
],
[],
),
])
}

pub fn flat(color: Colors) -> Attribute(a) {
case color {
Neutral ->
"text-neutral bg-neutral/20 hover:enabled:bg-neutral/30 [&+div]:text-neutral"
Primary ->
"text-primary bg-primary/20 hover:enabled:bg-primary/30 [&+div]:text-primary"
Secondary ->
"text-secondary bg-secondary/20 hover:enabled:bg-secondary/30 [&+div]:text-secondary"
Success ->
"text-success bg-success/20 hover:enabled:bg-success/30 [&+div]:text-success"
Info -> "text-info bg-info/20 hover:enabled:bg-info/30 [&+div]:text-info"
Warning ->
"text-warning bg-warning/20 hover:enabled:bg-warning/30 [&+div]:text-warning"
Danger ->
"text-danger bg-danger/20 hover:enabled:bg-danger/30 [&+div]:text-danger"
}
|> string.append(
" focus:outline-none focus:ring-2 focus:ring-current open:outline-none open:ring-2 open:ring-current",
)
|> class
}

pub fn outlined(color: Colors) -> Attribute(a) {
case color {
Neutral ->
"border-neutral focus:enabled:border-neutral open:enabled:border-neutral hover:enabled:border-neutral text-neutral [&+div]:text-neutral"
Primary ->
"border-primary focus:enabled:border-primary open:enabled:border-primary hover:enabled:border-primary text-primary [&+div]:text-primary"
Secondary ->
"border-secondary focus:enabled:border-secondary open:enabled:border-secondary hover:enabled:border-secondary text-secondary [&+div]:text-secondary"
Success ->
"border-success focus:enabled:border-success open:enabled:border-success hover:enabled:border-success text-success [&+div]:text-success"
Info ->
"border-info focus:enabled:border-info open:enabled:border-info hover:enabled:border-info text-info [&+div]:text-info"
Warning ->
"border-warning focus:enabled:border-warning open:enabled:border-warning hover:enabled:border-warning text-warning [&+div]:text-warning"
Danger ->
"border-danger focus:enabled:border-danger open:enabled:border-danger hover:enabled:border-danger text-danger [&+div]:text-danger"
}
|> string.append(
[
" bg-transparent border-2 border-opacity-50 placeholder-opacity-70",
"hover:enabled:border-opacity-100 focus:enabled:border-opacity-100 open:enabled:border-opacity-100",
"focus:outline-none focus:ring-2 focus:ring-current",
"open:outline-none open:ring-2 open:ring-current",
]
|> string.join(" "),
)
|> class
}

pub fn underlined(color: Colors) -> Attribute(a) {
case color {
Neutral -> "border-neutral text-neutral [&+div]:text-neutral"
Primary -> "border-primary text-primary [&+div]:text-primary"
Secondary -> "border-secondary text-secondary [&+div]:text-secondary"
Success -> "border-success text-success [&+div]:text-success"
Info -> "border-info text-info [&+div]:text-info"
Warning -> "border-warning text-warning [&+div]:text-warning"
Danger -> "border-danger text-danger [&+div]:text-danger"
}
|> string.append(
[
" bg-transparent border-opacity-20 border-b-2 outline-none rounded-b-none",
"focus:enabled:border-opacity-100 open:enabled:border-opacity-100",
]
|> string.join(" "),
)
|> class
}

pub fn sm() -> Attribute(a) {
class("rounded-sm pl-3.5 pr-9 py-1.5 text-sm")
}

pub fn md() -> Attribute(a) {
class("rounded-md pl-4 pr-10 py-2 text-base")
}

pub fn lg() -> Attribute(a) {
class("rounded-lg pl-5 pr-12 py-2.5 text-lg")
}
2 changes: 2 additions & 0 deletions app/src/gleez_ui.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ fn on_url_change(uri: Uri) -> Msg {
["docs", "components", "spinner"] -> OnRouteChange(route.Spinner)
["docs", "components", "skeleton"] -> OnRouteChange(route.Skeleton)
["docs", "components", "slider"] -> OnRouteChange(route.Slider)
["docs", "components", "select"] -> OnRouteChange(route.Select)
_ -> OnRouteChange(route.Home)
}
}
Expand Down Expand Up @@ -144,6 +145,7 @@ fn with_aside(model: Model) -> Element(Msg) {
route.Spinner -> page.spinner()
route.Skeleton -> page.skeleton()
route.Slider -> page.slider()
route.Select -> page.select()
_ -> page.home()
},
]),
Expand Down
17 changes: 11 additions & 6 deletions app/src/model/route.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub type Pages {
Spinner
Skeleton
Slider
Select
}

pub const home = "/"
Expand Down Expand Up @@ -74,6 +75,8 @@ pub const skeleton = "/docs/components/skeleton/"

pub const slider = "/docs/components/slider/"

pub const select = "/docs/components/select/"

pub type Status {
None
New
Expand Down Expand Up @@ -102,17 +105,17 @@ pub fn pages() -> List(Page) {
Page(input, [], None),
Page(link, [], None),
Page(chip, [], None),
Page(divider, [], Updated),
Page(divider, [], None),
Page(tooltip, [], None),
Page(avatar, [], None),
Page(badge, [], None),
Page(breadcrumbs, [], None),
Page(switch, [], None),
Page(kbd, [], New),
Page(checkbox, [], New),
Page(spinner, [], New),
Page(skeleton, [], New),
Page(slider, [], New),
Page(kbd, [], None),
Page(checkbox, [], None),
Page(spinner, [], None),
Page(skeleton, [], None),
Page(select, [], New),
]
|> sort_pages,
None,
Expand Down Expand Up @@ -144,6 +147,7 @@ pub fn to_path(page: Pages) -> String {
Spinner -> spinner
Skeleton -> skeleton
Slider -> slider
Select -> select
}
}

Expand All @@ -170,6 +174,7 @@ pub fn to_pages(uri: Uri) -> Pages {
p if p == spinner -> Spinner
p if p == skeleton -> Skeleton
p if p == slider -> Slider
p if p == select -> Select
_ -> Home
}
}
Expand Down
16 changes: 10 additions & 6 deletions app/src/pages/demo/demo.gleam
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import components/ui/slider.{slider}
import components/ui/select.{select}
import lustre/attribute.{class}
import lustre/element.{type Element}
import lustre/element/html.{div}
import lustre/element/html.{div, option}

pub fn demo() -> Element(a) {
div([class("flex flex-col gap-2 py-2 w-full max-w-xs")], [
slider([slider.solid(slider.Neutral), slider.sm()]),
slider([slider.solid(slider.Neutral), slider.md()]),
slider([slider.solid(slider.Neutral), slider.lg()]),
div([class("flex flex-col flex-wrap gap-4 justify-center w-full pt-8")], [
select([select.outlined(select.Neutral), select.md()], [option([], "Neutral")]),
select([select.outlined(select.Primary), select.md()], [option([], "Primary")]),
select([select.outlined(select.Secondary), select.md()], [option([], "Secondary")]),
select([select.outlined(select.Success), select.md()], [option([], "Success")]),
select([select.outlined(select.Info), select.md()], [option([], "Info")]),
select([select.outlined(select.Warning), select.md()], [option([], "Warning")]),
select([select.outlined(select.Danger), select.md()], [option([], "Danger")]),
])
}
46 changes: 46 additions & 0 deletions app/src/pages/docs/components/select/attributes.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import components/ui/select.{select}
import lustre/element.{type Element}
import lustre/element/html.{option}
import pages/docs/sections/section

pub fn attributes() -> Element(a) {
section.attributes([
section.attribute(
"Size",
"
- `sm()`: Small Size
- `md()`: Medium Size
- `lg()`: Large Size
",
[
select([select.outlined(select.Neutral), select.sm()], [
option([], "Small"),
]),
select([select.outlined(select.Neutral), select.md()], [
option([], "Medium"),
]),
select([select.outlined(select.Neutral), select.lg()], [
option([], "Large"),
]),
],
size_code(),
),
])
}

fn size_code() -> String {
"
import components/ui/select.{select}
import lustre/attribute.{class}
import lustre/element.{type Element}
import lustre/element/html.{div, option}

pub fn demo() -> Element(a) {
div([class(\"flex flex-col flex-wrap gap-4 justify-center w-full\")], [
select([select.outlined(select.Neutral), select.sm()], [option([], \"Small\")]),
select([select.outlined(select.Neutral), select.md()], [option([], \"Medium\")]),
select([select.outlined(select.Neutral), select.lg()], [option([], \"Large\")]),
])
}
"
}
17 changes: 17 additions & 0 deletions app/src/pages/docs/components/select/select.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import components/prose.{prose}
import lustre/element.{type Element}
import pages/docs/components/select/attributes.{attributes}
import pages/docs/components/select/variants.{variants}
import pages/docs/sections/section

pub fn docs() -> Element(a) {
prose([], [
section.intro(
"Select",
"Select components are used for collecting user provided information from a list of options.",
),
section.installation("gleam run -m gleez add select"),
variants(),
attributes(),
])
}
Loading