From 773efd0742a253ddb540f89dc08305d349d8a482 Mon Sep 17 00:00:00 2001 From: Kosta <68782786+KostaD02@users.noreply.github.com> Date: Wed, 30 Apr 2025 20:04:41 +0400 Subject: [PATCH 1/3] feat: button group --- scss/components/_index.scss | 4 +- scss/components/{ => button}/_button.scss | 2 +- scss/components/button/_group.scss | 59 +++++++ scss/components/button/_index.scss | 2 + stories/Introduction.mdx | 14 +- .../components/button-group/button-group.mdx | 35 ++++ .../button-group/button-group.stories.ts | 149 ++++++++++++++++++ stories/utilities/flex/flex.stories.ts | 9 +- 8 files changed, 263 insertions(+), 11 deletions(-) rename scss/components/{ => button}/_button.scss (98%) create mode 100644 scss/components/button/_group.scss create mode 100644 scss/components/button/_index.scss create mode 100644 stories/components/button-group/button-group.mdx create mode 100644 stories/components/button-group/button-group.stories.ts diff --git a/scss/components/_index.scss b/scss/components/_index.scss index 83fdbbe..551cc21 100644 --- a/scss/components/_index.scss +++ b/scss/components/_index.scss @@ -1,9 +1,9 @@ @use "./containers"; -@use "./button"; @use "./modal"; @use "./chips"; @use "./spinner"; @use "./breadcrumb"; @use "./card"; @use "./promo-card"; -@use "./form/index"; +@use "./button/index" as button; +@use "./form/index" as form; diff --git a/scss/components/_button.scss b/scss/components/button/_button.scss similarity index 98% rename from scss/components/_button.scss rename to scss/components/button/_button.scss index dbec5a2..058aece 100644 --- a/scss/components/_button.scss +++ b/scss/components/button/_button.scss @@ -1,5 +1,5 @@ @use "sass:map"; -@use "../variables/global" as *; +@use "../../variables/global" as *; .btn { --#{$prefix}btn-weight: 400; diff --git a/scss/components/button/_group.scss b/scss/components/button/_group.scss new file mode 100644 index 0000000..da29569 --- /dev/null +++ b/scss/components/button/_group.scss @@ -0,0 +1,59 @@ +@use "sass:map"; +@use "../../variables/global" as *; + +.btn-group { + --#{$prefix}btn-group-radius: var(--#{$prefix}border-radius); + + position: relative; + display: inline-flex; + vertical-align: middle; + border-radius: var(--#{$prefix}border-radius); + background-color: transparent; + + .btn { + position: relative; + flex: 1 1 auto; + border-radius: 0; + + &:first-child { + border-top-left-radius: var(--#{$prefix}btn-group-radius); + border-bottom-left-radius: var(--#{$prefix}btn-group-radius); + } + + &:last-child { + border-top-right-radius: var(--#{$prefix}btn-group-radius); + border-bottom-right-radius: var(--#{$prefix}btn-group-radius); + } + } + + &.btn-group-vertical { + flex-direction: column; + align-items: flex-start; + justify-content: center; + + .btn { + &:first-child { + border-radius: 0; + + border-top-left-radius: var(--#{$prefix}btn-group-radius); + border-top-right-radius: var(--#{$prefix}btn-group-radius); + } + + &:last-child { + border-radius: 0; + border-bottom-left-radius: var(--#{$prefix}btn-group-radius); + border-bottom-right-radius: var(--#{$prefix}btn-group-radius); + } + } + } +} + +@each $size, $styles in $button-sizes { + .btn-group-#{"" + $size} { + .btn { + --#{$prefix}btn-font-size: #{map.get($styles, font-size)}; + --#{$prefix}btn-padding-x: #{map.get($styles, padding-x)}; + --#{$prefix}btn-padding-y: #{map.get($styles, padding-y)}; + } + } +} diff --git a/scss/components/button/_index.scss b/scss/components/button/_index.scss new file mode 100644 index 0000000..ae15a7c --- /dev/null +++ b/scss/components/button/_index.scss @@ -0,0 +1,2 @@ +@use "./button"; +@use "./group"; diff --git a/stories/Introduction.mdx b/stories/Introduction.mdx index f12133e..b7bd87c 100644 --- a/stories/Introduction.mdx +++ b/stories/Introduction.mdx @@ -1,10 +1,12 @@ import Logo from './assets/logo.png'; -

Educata Styles

+
+

Educata Styles

-Educata Styles + Educata Styles -

- Educata's styling package. The [project code](https://github.com/educata/educata-style) is - licensed under the [MIT License](https://github.com/educata/educata-style/blob/main/LICENSE). -

\ No newline at end of file +

+ Educata's styling package. The [project code](https://github.com/educata/educata-style) is + licensed under the [MIT License](https://github.com/educata/educata-style/blob/main/LICENSE). +

+
diff --git a/stories/components/button-group/button-group.mdx b/stories/components/button-group/button-group.mdx new file mode 100644 index 0000000..8c9147f --- /dev/null +++ b/stories/components/button-group/button-group.mdx @@ -0,0 +1,35 @@ +import { Canvas, Meta } from '@storybook/blocks'; + +import * as ButtonGroupStories from './button-group.stories.ts'; + +# Button groups + +Group a series of buttons together on a single line or stack them in a vertical column. + +## Example + +Wrap a series of buttons with `.btn` in `.btn-group`. + + + +### Mixed + + + +### Outlined styles + + + + + +### Vertical + +Add the `.btn-group-vertical` class to stack buttons vertically. + + + +### Sizes + +Add the `.btn-group-sm` or `.btn-group-lg` class to create small or large button groups. + + \ No newline at end of file diff --git a/stories/components/button-group/button-group.stories.ts b/stories/components/button-group/button-group.stories.ts new file mode 100644 index 0000000..1727119 --- /dev/null +++ b/stories/components/button-group/button-group.stories.ts @@ -0,0 +1,149 @@ +import { Meta, StoryObj } from "@storybook/html"; +import { VARIATIONS } from "../../shared"; + +const meta: Meta = { + title: "Components/Button Group", +}; + +export default meta; +type Story = StoryObj; + +export const Example: Story = { + tags: ["!dev"], + render: () => { + return ` +
+ + + +
+`; + }, +}; + +export const Mixed: Story = { + tags: ["!dev"], + render: () => { + return ` +
+ + + +
+`; + }, +}; + +export const Outlined: Story = { + tags: ["!dev"], + render: () => { + return ` +
+ + + +
+`; + }, +}; + +export const OutlinedMixed: Story = { + tags: ["!dev"], + render: () => { + return ` +
+ + + +
+`; + }, +}; + +export const Vertical: Story = { + tags: ["!dev"], + render: () => { + return ` +
+ + + + +
+`; + }, +}; + +export const Sizes: Story = { + tags: ["!dev"], + render: () => { + return ` +
+ + + +
+
+ + + +
+
+ + + +
+`; + }, +}; + +export const Group: Story = { + args: { + count: 3, + vertical: false, + size: "default", + variation: "secondary", + }, + argTypes: { + count: { + control: { + type: "range", + min: 1, + max: 9, + }, + }, + size: { + control: "select", + options: ["sm", "default", "lg"], + }, + variation: { + control: "select", + options: VARIATIONS, + }, + }, + parameters: { + backgrounds: { + default: "dark", + }, + }, + render: (args) => { + return ` +
+ ${new Array(args.count) + .fill(0) + .map((_, i) => { + return ``; + }) + .join("")} +
+`; + }, +}; diff --git a/stories/utilities/flex/flex.stories.ts b/stories/utilities/flex/flex.stories.ts index 7696313..20d3311 100644 --- a/stories/utilities/flex/flex.stories.ts +++ b/stories/utilities/flex/flex.stories.ts @@ -405,6 +405,7 @@ export const Flex: Story = { justifyContent: "center", alignItems: "center", alignContent: "center", + direction: "row", }, argTypes: { elementCount: { @@ -444,16 +445,20 @@ export const Flex: Story = { control: "select", options: ["flex-start", "flex-end", "center", "baseline", "stretch"], }, + direction: { + control: "select", + options: ["row", "row-reverse", "column", "column-reverse"], + }, }, render: (args) => { const div = document.createElement("div"); - div.classList.add("d-flex", "m-auto", "box-wrapper", "p-3", "w-100"); + div.classList.add("d-flex", "m-auto", "box-wrapper", "p-3", "w-100", "vh-100"); div.classList.add(`justify-content-${args.justifyContent}`); div.classList.add(`align-items-${args.alignItems}`); div.classList.add(`align-content-${args.alignContent}`); div.classList.add(`flex-${args.wrap}`); - div.style.height = "200px"; div.classList.add(`gap-${args.gapLevel}`); + div.classList.add(`flex-${args.direction}`); const fragment = document.createDocumentFragment(); for (let i = 0; i < args.elementCount; i++) { From 620ac5077cfb3469f0a43884626e33c1d26eabbe Mon Sep 17 00:00:00 2001 From: Kosta <68782786+KostaD02@users.noreply.github.com> Date: Wed, 30 Apr 2025 21:18:08 +0400 Subject: [PATCH 2/3] feat: close button --- scss/components/_modal.scss | 6 -- scss/components/button/_button.scss | 1 + scss/components/button/_close.scss | 58 ++++++++++++++ scss/components/button/_index.scss | 1 + .../components/close-button/close-button.mdx | 33 ++++++++ .../close-button/close-button.stories.ts | 76 +++++++++++++++++++ stories/components/modal/modal.mdx | 4 +- stories/components/modal/modal.stories.ts | 8 +- stories/components/spinner/spinner.stories.ts | 4 +- 9 files changed, 177 insertions(+), 14 deletions(-) create mode 100644 scss/components/button/_close.scss create mode 100644 stories/components/close-button/close-button.mdx create mode 100644 stories/components/close-button/close-button.stories.ts diff --git a/scss/components/_modal.scss b/scss/components/_modal.scss index 8cef4a1..34e073c 100644 --- a/scss/components/_modal.scss +++ b/scss/components/_modal.scss @@ -120,12 +120,6 @@ font-weight: var(--#{$prefix}font-weight-700); line-height: 1.5; } - - .modal-close { - // TODO: Update to icon styles - font-size: var(--#{$prefix}font-size-xxl); - cursor: pointer; - } } .modal-body { diff --git a/scss/components/button/_button.scss b/scss/components/button/_button.scss index 058aece..17e5cbf 100644 --- a/scss/components/button/_button.scss +++ b/scss/components/button/_button.scss @@ -15,6 +15,7 @@ --#{$prefix}btn-border: var(--#{$prefix}border-width) var(--#{$prefix}border-style) var(--#{$prefix}border-color); --#{$prefix}btn-border-color: var(--#{$prefix}btn-bg); + --#{$prefix}btn-transition: ease-in-out; display: inline-block; padding: var(--#{$prefix}btn-padding-y) var(--#{$prefix}btn-padding-x); diff --git a/scss/components/button/_close.scss b/scss/components/button/_close.scss new file mode 100644 index 0000000..edd4531 --- /dev/null +++ b/scss/components/button/_close.scss @@ -0,0 +1,58 @@ +@use "../../variables/global" as *; + +.btn-close { + --#{$prefix}-btn-close-height: 1rem; + --#{$prefix}-btn-close-width: 1rem; + --#{$prefix}-btn-close-padding: 0.25rem; + --#{$prefix}-btn-close-bg: transparent; + --#{$prefix}-btn-close-opacity: 0.8; + --#{$prefix}-btn-close-hover-opacity: 1; + --#{$prefix}-btn-close-disabled-opacity: 0.5; + --#{$prefix}-btn-close-transition: ease-in-out; + --#{$prefix}-btn-close-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23ffffff'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414'/%3e%3c/svg%3e"); + + display: inline-flex; + justify-content: center; + align-items: center; + cursor: pointer; + width: var(--#{$prefix}-btn-close-width); + height: var(--#{$prefix}-btn-close-height); + padding: var(--#{$prefix}-btn-close-padding); + opacity: var(--#{$prefix}-btn-close-opacity); + background-image: var(--#{$prefix}-btn-close-image); + background-size: var(--#{$prefix}-btn-close-width) var(--#{$prefix}-btn-close-height); + background-color: var(--#{$prefix}-btn-close-bg); + background-repeat: no-repeat; + background-position: center; + transition: opacity ease-in-out 0.15s; + + &:hover, + &:focus { + outline: none; + opacity: var(--#{$prefix}-btn-close-hover-opacity); + } + + &:disabled { + cursor: not-allowed; + opacity: var(--#{$prefix}-btn-close-disabled-opacity); + } + + &.btn-close-sm { + --#{$prefix}-btn-close-height: 0.75rem; + --#{$prefix}-btn-close-width: 0.75rem; + --#{$prefix}-btn-close-padding: 0.125rem; + } + + &.btn-close-lg { + --#{$prefix}-btn-close-height: 1.5rem; + --#{$prefix}-btn-close-width: 1.5rem; + --#{$prefix}-btn-close-padding: 0.5rem; + } + + &.btn-close-black { + --#{$prefix}-btn-close-opacity: 0.5; + --#{$prefix}-btn-close-hover-opacity: 0.75; + --#{$prefix}-btn-close-disabled-opacity: 0.2; + --#{$prefix}-btn-close-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23000'%3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414'/%3e%3c/svg%3e"); + } +} diff --git a/scss/components/button/_index.scss b/scss/components/button/_index.scss index ae15a7c..11ce133 100644 --- a/scss/components/button/_index.scss +++ b/scss/components/button/_index.scss @@ -1,2 +1,3 @@ @use "./button"; @use "./group"; +@use "./close"; diff --git a/stories/components/close-button/close-button.mdx b/stories/components/close-button/close-button.mdx new file mode 100644 index 0000000..047fcb6 --- /dev/null +++ b/stories/components/close-button/close-button.mdx @@ -0,0 +1,33 @@ +import { Canvas, Meta } from '@storybook/blocks'; + +import * as CloseButton from './close-button.stories.ts'; + +# Close button + +A generic close button for dismissing content like modals and alerts. + +## Example + +Provide an option to dismiss or close a component with `.btn-close`. + + + +> Be sure to include text for screen readers, as we've done with `aria-label`. + +## Disabled state + +Disabled close buttons change their opacity. + + + +## Dark variant + +The dark variant of the close button is used in dark mode. + + + +## Sizes + +The close button can be used in different sizes. We have a small and large variant. + + \ No newline at end of file diff --git a/stories/components/close-button/close-button.stories.ts b/stories/components/close-button/close-button.stories.ts new file mode 100644 index 0000000..bd80316 --- /dev/null +++ b/stories/components/close-button/close-button.stories.ts @@ -0,0 +1,76 @@ +import { Meta, StoryObj } from "@storybook/html"; +import { VARIATIONS } from "../../shared"; + +const meta: Meta = { + title: "Components/Close button", +}; + +export default meta; +type Story = StoryObj; + +export const Example: Story = { + tags: ["!dev"], + render: () => { + return ` + +`; + }, +}; + +export const Disabled: Story = { + tags: ["!dev"], + render: () => { + return ` + +`; + }, +}; + +export const Black: Story = { + tags: ["!dev"], + render: () => { + return ` + + +`; + }, +}; + +export const Sizes: Story = { + tags: ["!dev"], + render: () => { + return ` + + + +`; + }, +}; + +export const Button: Story = { + args: { + size: "default", + dark: false, + disabled: false, + }, + argTypes: { + size: { + control: "select", + options: ["sm", "default", "lg"], + }, + }, + parameters: { + backgrounds: { + default: "dark", + }, + }, + render: (args) => { + return ` +
+ +
+`; + }, +}; diff --git a/stories/components/modal/modal.mdx b/stories/components/modal/modal.mdx index 6f660bd..e66b7c6 100644 --- a/stories/components/modal/modal.mdx +++ b/stories/components/modal/modal.mdx @@ -8,7 +8,7 @@ The structure inside it should be the same for every modal.